Skip to content

Commit cf2c2f0

Browse files
committed
fix(docs): cleanup storeAs section of Firestore docs
1 parent 8cf7a2a commit cf2c2f0

File tree

2 files changed

+113
-70
lines changed

2 files changed

+113
-70
lines changed

docs/firestore.md

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Firestore
22

3-
To correctly begin using firestore, make sure you have the following:
4-
* `v2.0.0-beta.11` or higher (most like to use `next` tag in package.json)
3+
To begin using Firestore with `react-redux-firebase`, make sure you have the following:
4+
* `v2.0.0` or higher of `react-redux-firebase`
55
* Install `redux-firestore` in your project using `npm i --save redux-firestore@latest`
66
* `firestore` imported with `import 'firebase/firestore'`
77
* `firestore` initialize with `firebase.firestore()`
@@ -17,27 +17,26 @@ import 'firebase/firestore' // add this to use Firestore
1717
import { reactReduxFirebase, firebaseReducer } from 'react-redux-firebase'
1818
import { reduxFirestore, firestoreReducer } from 'redux-firestore'
1919

20-
const firebaseConfig = {}
21-
2220
// react-redux-firebase config
2321
const rrfConfig = {
2422
userProfile: 'users',
2523
// useFirestoreForProfile: true // Firestore for Profile instead of Realtime DB
2624
}
2725

28-
// initialize firebase instance
29-
firebase.initializeApp(firebaseConfig) // <- new to v2.*.*
26+
// initialize firebase instance with config from console
27+
const firebaseConfig = {}
28+
firebase.initializeApp(firebaseConfig)
3029

3130
// initialize Firestore
3231
firebase.firestore()
3332

34-
// Add reduxReduxFirebase enhancer when making store creator
33+
// Add BOTH store enhancers when making store creator
3534
const createStoreWithFirebase = compose(
3635
reactReduxFirebase(firebase, rrfConfig),
3736
reduxFirestore(firebase)
3837
)(createStore)
3938

40-
// Add Firebase to reducers
39+
// Add firebase and firestore to reducers
4140
const rootReducer = combineReducers({
4241
firebase: firebaseStateReducer,
4342
firestore: firestoreReducer
@@ -216,13 +215,38 @@ export default enhance(SomeComponent)
216215

217216
For more information [on using recompose visit the docs](https://github.com/acdlite/recompose/blob/master/docs/API.md)
218217

219-
## storeAs {#populate}
218+
### storeAs {#storeAs}
219+
220+
By default the results of queries are stored in redux under the path of the query. If you would like to change where the query results are stored in redux, use `storeAs`.
220221

221-
`storeAs` is not yet supported for the Firestore integration, but will be coming soon.
222+
#### Examples
223+
1. Querying the same path with different query parameters
224+
225+
```js
226+
import { compose } from 'redux'
227+
import { connect } from 'react-redux'
228+
import { firestoreConnect } from 'react-redux-firebase'
229+
const myProjectsReduxName = 'myProjects'
230+
231+
compose(
232+
firestoreConnect(props => [
233+
{ path: 'projects' },
234+
{
235+
path: 'projects',
236+
storeAs: myProjectsReduxName,
237+
queryParams: ['orderByChild=uid', '123']
238+
}
239+
]),
240+
connect((state, props) => ({
241+
projects: state.firestore.data.projects,
242+
myProjects: state.firestore.data[myProjectsReduxName], // use storeAs path to gather from redux
243+
}))
244+
)
245+
```
222246

223247
## Populate {#populate}
224248

225-
Populate is not yet supported for the Firestore integration, but will be coming soon.
249+
Populate is not yet supported for the Firestore integration, but will be coming soon. Progress can be tracked [within issue #48](https://github.com/prescottprue/redux-firestore/issues/48).
226250

227251
## More Info {#more}
228252

docs/queries.md

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ import { connect } from 'react-redux'
1717
import { compose } from 'redux'
1818
import { withFirebase } from 'react-redux-firebase'
1919

20+
const todosPath = 'todos'
21+
2022
const Todos = ({ firebase, todos }) => (
2123
<div>
2224
<h1>Todos</h1>
2325
<div>
2426
{JSON.stringify(todos, null, 2)}
2527
</div>
26-
<button onClick={() => firebase.watchEvent('value', 'todos')}>
28+
<button onClick={() => firebase.watchEvent('value', todosPath)}>
2729
Load Todos
2830
</button>
2931
</div>
@@ -32,7 +34,8 @@ const Todos = ({ firebase, todos }) => (
3234
export default compose(
3335
withFirebase,
3436
connect((state) => ({
35-
todos: state.firebase.data.todos
37+
todos: state.firebase.data[todosPath],
38+
// todos: state.firebase.ordered[todosPath] // for ordered data (array)
3639
}))
3740
)(Todos)
3841
```
@@ -79,44 +82,6 @@ export default compose(
7982

8083
By default the results of queries are stored in redux under the path of the query. If you would like to change where the query results are stored in redux, use [`storeAs` (more below)](#storeAs).
8184

82-
#### Ordered vs Data (by key)
83-
84-
##### data {#data}
85-
86-
In order to get data from state by key, use `data`.
87-
88-
###### Examples
89-
1. Get an object of projects by key
90-
91-
```js
92-
compose(
93-
firebaseConnect(props => [
94-
{ path: 'projects' }
95-
]),
96-
connect((state, props) => ({
97-
projects: state.firebase.data.projects,
98-
}))
99-
)
100-
```
101-
102-
##### ordered {#ordered}
103-
104-
In order to get ordered data, use `ordered`
105-
106-
###### Examples
107-
1. Get list of projects ordered by key
108-
109-
```js
110-
compose(
111-
firebaseConnect(props => [
112-
{ path: 'projects', queryParams: ['orderByKey'] }
113-
]),
114-
connect((state, props) => ({
115-
projects: state.firebase.ordered.projects,
116-
}))
117-
)
118-
```
119-
12085
#### Waiting For Data To Load {#loading}
12186

12287
The `isLoaded` utility is helpful in checking to see if data has loaded. Check loaded state by passing it a list of props:
@@ -139,13 +104,9 @@ const Todos = ({ firebase, todos }) => {
139104
return (
140105
<div>
141106
<h1>Todos</h1>
142-
<ul>
143-
{
144-
Object.keys(todos).map((key, id) =>
145-
<TodoItem key={key} id={id} todo={todos[key]}/>
146-
)
147-
}
148-
</ul>
107+
<div>
108+
{JSON.stringify(todos, null, 2)}
109+
</div>
149110
</div>
150111
)
151112
}
@@ -154,11 +115,9 @@ export default compose(
154115
firebaseConnect((props) => [
155116
{ path: 'todos' } // string equivalent 'todos'
156117
]),
157-
connect(
158-
(state) => ({
159-
todos: state.firebase.data.todos,
160-
})
161-
)
118+
connect((state) => ({
119+
todos: state.firebase.data.todos,
120+
}))
162121
)(Todos)
163122
```
164123

@@ -167,7 +126,7 @@ export default compose(
167126
Using [`recompose`](https://github.com/acdlite/recompose) is a nice way to keep your react code clean and functional. Useful Higher Order Components are offered such as `branch` (similar to the `if` statements from the last example) making for much cleaner construction of your own HOCs:
168127

169128
```js
170-
import { some } from 'lodash'
129+
import { get, some } from 'lodash'
171130
import LoadingSpinner from 'components/LoadingSpinner' // or wherever your spinner component is
172131
import { isLoaded } from 'react-redux-firebase'
173132
import {
@@ -177,13 +136,27 @@ import {
177136
renderComponent
178137
} from 'recompose'
179138

180-
// HOC that shows loading spinner component while condition is true
181-
export const spinnerWhile = condition =>
182-
branch(condition, renderComponent(LoadingSpinner))
139+
// HOC that shows a component while condition is true
140+
export const renderWhile = (condition, component) =>
141+
branch(condition, renderComponent(component))
183142

184143
// HOC that shows loading spinner component while list of propNames are loading
185144
export const spinnerWhileLoading = propNames =>
186-
spinnerWhile(props => some(propNames, name => !isLoaded(props[name])))
145+
renderWhile(
146+
props => some(propNames, name => !isLoaded(get(props, name))),
147+
LoadingSpinner
148+
)
149+
150+
// HOC that shows a component while any of a list of props isEmpty
151+
export const renderIfEmpty = (propsNames, component) =>
152+
renderWhile(
153+
// Any of the listed prop name correspond to empty props (supporting dot path names)
154+
props => some(propNames, (name) => {
155+
const propValue = get(props, name)
156+
return isLoaded(propValue) && isEmpty(propValue)
157+
}),
158+
component
159+
)
187160
```
188161

189162
That can then be used in HOC compositions to wait for data to load like so:
@@ -193,10 +166,56 @@ import { compose } from 'redux'
193166
import { connect } from 'react-redux'
194167
import { firebaseConnect } from 'react-redux-firebase'
195168

169+
const EmptyMessage = () => <div>No Projects Found</div>
170+
196171
const enhance = compose(
172+
// set/unset listener to "projects" path on component mount/unmount
197173
firebaseConnect(['projects']),
174+
// map projects from redux state to props
198175
connect(({ firebase: { data: { projects } } }) => ({ projects })),
199-
spinnerWhileLoading(['projects'])
176+
// show loading spinner while projects are loading
177+
spinnerWhileLoading(['projects']),
178+
// render empty message if projects are not found
179+
renderIfEmpty(['projects'], EmptyMessage)
180+
)
181+
```
182+
183+
#### Formats
184+
Two portions of redux state contain data resulting from queries. `state.firebase.ordered` contains array formatted data while `state.firebase.data` contains data store by key
185+
186+
##### data {#data}
187+
188+
In order to get data from state by key, use `data`.
189+
190+
###### Examples
191+
1. Get an object of projects by key
192+
193+
```js
194+
compose(
195+
firebaseConnect(props => [
196+
{ path: 'projects' }
197+
]),
198+
connect((state, props) => ({
199+
projects: state.firebase.data.projects,
200+
}))
201+
)
202+
```
203+
204+
##### ordered {#ordered}
205+
206+
In order to get ordered data, use `ordered`
207+
208+
###### Examples
209+
1. Get list of projects ordered by key
210+
211+
```js
212+
compose(
213+
firebaseConnect(props => [
214+
{ path: 'projects', queryParams: ['orderByKey'] }
215+
]),
216+
connect((state, props) => ({
217+
projects: state.firebase.ordered.projects,
218+
}))
200219
)
201220
```
202221

@@ -484,7 +503,7 @@ compose(
484503

485504
#### Why?
486505

487-
Data is stored in redux under the path of the query for convince. This means that two different queries to the same path (i.e. `todos`) will both place data into `state.data.todos` even if their query parameters are different.
506+
Data is stored in redux under the path of the query for convenience. This means that two different queries to the same path (i.e. `todos`) will both place data into `state.data.todos` even if their query parameters are different.
488507

489508

490509
### Populate {#populate}

0 commit comments

Comments
 (0)