Skip to content

Commit 11ee53a

Browse files
authored
v2.0.0-beta.17 (prescottprue#334)
* fix(populate): undefined populate child responds unmodified as expected - prescottprue#310 * fix(auth): `UNLOAD_PROFILE` action type no longer dispatched (did not fix issue) - prescottprue#301 * feat(populate): support for populating ordered data with multiple populates where one populate child missing * feat(query): parsed query param added to allow disabling of automatic parsing - prescottprue#302 * feat(config): `preserveOnLogin` config option added to allow preserving of pieces of state affected by `LOGIN` action (called by `login` action creator) * feat(tests): test added to check profile state consistency on `LOGIN` dispatch - prescottprue#301 * feat(tests): tests added for `getVal` helper * feat(tests): Unit tests added for populating ordered data
1 parent aecc6b9 commit 11ee53a

13 files changed

+506
-8482
lines changed

docs/api/helpers.md

+78-15
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { connect } from 'react-redux'
3131
import { firebaseConnect, getVal } from 'react-redux-firebase'
3232

3333
const enhance = compose(
34-
firebaseConnect(['/todos/user1']),
34+
firebaseConnect(['todos/user1']),
3535
connect(({ firebase }) => ({
3636
// this.props.todos loaded from state.firebase.data.todos
3737
todos: getVal(firebase, 'data/todos/user1')
@@ -60,18 +60,21 @@ _Default Value_
6060
import { compose } from 'redux'
6161
import { connect } from 'react-redux'
6262
import { firebaseConnect, getVal } from 'react-redux-firebase'
63+
6364
const defaultValue = {
6465
1: {
6566
text: 'Example Todo'
6667
}
6768
}
69+
6870
const enhance = compose(
69-
firebaseConnect(['/todos/user1']),
71+
firebaseConnect(['todos/user1']),
7072
connect(({ firebase }) => ({
7173
// this.props.todos loaded from state.firebase.data.todos
7274
todos: getVal(firebase, 'data/todos/user1', defaultValue)
7375
})
7476
)
77+
7578
export default enhance(SomeComponent)
7679
```
7780
@@ -90,10 +93,38 @@ Detect whether items are loaded yet or not
9093
**Examples**
9194
9295
```javascript
93-
import React, { Component } from 'react'
96+
import React from 'react'
9497
import PropTypes from 'prop-types'
98+
import { compose } from 'redux'
9599
import { connect } from 'react-redux'
96-
import { firebaseConnect, isLoaded } from 'react-redux-firebase'
100+
import { firebaseConnect, isLoaded, isEmpty } from 'react-redux-firebase'
101+
102+
const enhance = compose(
103+
firebaseConnect(['todos']),
104+
connect(({ firebase: { data: { todos } } }) => ({
105+
todos // state.firebase.data.todos from redux passed as todos prop
106+
}))
107+
)
108+
109+
const Todos = ({ todos }) => {
110+
// Message for if todos are loading
111+
if(!isLoaded(todos)) {
112+
return <span>Loading...</span>
113+
}
114+
115+
// Message if todos are empty
116+
if(isEmpty(todos)) {
117+
return <span>No Todos Found</span>
118+
}
119+
120+
return <div><pre>{JSON.stringify(todos, null, 2)}</pre></div>
121+
}
122+
123+
Todos.propTypes = {
124+
todos: PropTypes.object
125+
}
126+
127+
export default enhance(Todos)
97128
```
98129
99130
Returns **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether or not item is loaded
@@ -111,10 +142,38 @@ Detect whether items are empty or not
111142
**Examples**
112143
113144
```javascript
114-
import React, { Component } from 'react'
145+
import React from 'react'
115146
import PropTypes from 'prop-types'
147+
import { compose } from 'redux'
116148
import { connect } from 'react-redux'
117-
import { firebaseConnect, isEmpty } from 'react-redux-firebase'
149+
import { firebaseConnect, isEmpty, isLoaded } from 'react-redux-firebase'
150+
151+
const enhance = compose(
152+
firebaseConnect(['todos']),
153+
connect(({ firebase: { data: { todos } } }) => ({
154+
todos // state.firebase.data.todos from redux passed as todos prop
155+
}))
156+
)
157+
158+
const Todos = ({ todos }) => {
159+
// Message for if todos are loading
160+
if(!isLoaded(todos)) {
161+
return <span>Loading...</span>
162+
}
163+
164+
// Message if todos are empty
165+
if(isEmpty(todos)) {
166+
return <span>No Todos Found</span>
167+
}
168+
169+
return <todos>{JSON.stringify(todos)}</todos>
170+
}
171+
172+
Todos.propTypes = {
173+
todos: PropTypes.object
174+
}
175+
176+
export default enhance(Todos)
118177
```
119178
120179
Returns **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether or not item is empty
@@ -135,20 +194,24 @@ Populate with data from redux.
135194
_Basic_
136195
137196
```javascript
197+
import { compose } from 'redux'
138198
import { connect } from 'react-redux'
139199
import { firebaseConnect } from 'react-redux-firebase'
140200
const populates = [{ child: 'owner', root: 'users' }]
141201

142-
const fbWrapped = firebaseConnect([
143-
{ path: '/todos', populates } // load "todos" and matching "users" to redux
144-
])(App)
202+
const enhance = compose(
203+
firebaseConnect([
204+
{ path: 'todos', populates } // load "todos" and matching "users" to redux
205+
]),
206+
connect((state) => ({
207+
// this.props.todos loaded from state.firebase.data.todos
208+
// each todo has child 'owner' populated from matching uid in 'users' root
209+
// for loading un-populated todos use state.firebase.data.todos
210+
todos: populate(state.firebase, 'todos', populates),
211+
})
212+
)
145213

146-
export default connect((state) => ({
147-
// this.props.todos loaded from state.firebase.data.todos
148-
// each todo has child 'owner' populated from matching uid in 'users' root
149-
// for loading un-populated todos use state.firebase.data.todos
150-
todos: populate(state.firebase, 'todos', populates),
151-
}))(fbWrapped)
214+
export default enhance(SomeComponent)
152215
```
153216
154217
Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Data located at path within Immutable Object

docs/queries.md

+25-1
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,13 @@ queryParams: [`limitToFirst=${limitToFirst}`, `startAt=${startAt}`, 'orderByValu
161161
queryParams: ['orderByValue', `limitToFirst=${limitToFirst}`, `startAt=${startAt}`],
162162
```
163163

164-
If you would like to prevent parsing yourself (i.e. keep limit values as strings), you can pass [`notParsed`](#notParsed) as a queryParam:
164+
If you would like to prevent or cause parsing of query params yourself, you can pass [`notParsed`](#notParsed) or [`parsed`](#parsed) as a queryParam:
165165

166166
```js
167167
// limitToFirst and startAt remain as strings and are NOT automatically parsed
168168
queryParams: ['notParsed', `limitToFirst=${limitToFirst}`, `startAt=${startAt}`, 'orderByValue'],
169+
// limitToFirst and startAt are parsed into numbers if possible
170+
queryParams: ['parsed', `limitToFirst=${limitToFirst}`, `startAt=${startAt}`, 'orderByValue'],
169171
```
170172

171173
More on [`notParsed` below](#notParsed)
@@ -344,6 +346,7 @@ firebaseConnect([
344346
])
345347
```
346348

349+
347350
## notParsed {#notParsed}
348351

349352
Can be used to keep internal parsing from happening. Useful when attempting to search a number string using `equalTo`
@@ -363,6 +366,27 @@ firebaseConnect([
363366
])
364367
```
365368

369+
## parsed {#parsed}
370+
371+
Internally parse following query params. Useful when attempting to parse
372+
373+
**NOTE**: `orderByChild`, `orderByPriority`, and `orderByValue` will cause this to be enabled by default. Parsing will remain enabled for the rest of the query params until `notParsed` is called.
374+
375+
#### Examples
376+
1. Order by child parameter equal to a number string. Equivalent of searching for `'123'` (where as not using `notParsed` would search for children equal to `123`)
377+
```js
378+
firebaseConnect([
379+
{
380+
path: '/todos',
381+
queryParams: [
382+
'parsed', // causes automatic parsing
383+
'equalTo=123' // 123 is treated as a number instead of a string
384+
'orderByChild=createdBy',
385+
]
386+
}
387+
])
388+
```
389+
366390
## storeAs {#populate}
367391

368392
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`:

package-lock.json

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-redux-firebase",
3-
"version": "2.0.0-beta.16",
3+
"version": "2.0.0-beta.17",
44
"description": "Redux integration for Firebase. Comes with a Higher Order Components for use with React.",
55
"main": "lib/index.js",
66
"module": "es/index.js",
@@ -56,12 +56,6 @@
5656
"redux-react-firebase"
5757
],
5858
"dependencies": {
59-
"gitbook-plugin-anchorjs": "^1.1.1",
60-
"gitbook-plugin-edit-link": "^2.0.2",
61-
"gitbook-plugin-ga": "^1.0.1",
62-
"gitbook-plugin-github": "^2.0.0",
63-
"gitbook-plugin-prism": "^2.3.0",
64-
"gitbook-plugin-versions-select": "^0.1.1",
6559
"hoist-non-react-statics": "^2.3.1",
6660
"lodash": "^4.17.4",
6761
"prop-types": "^15.5.10",

src/actions/auth.js

+16-4
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,19 @@ const getProfileFromSnap = (snap) => {
7373
export const handleProfileWatchResponse = (dispatch, firebase, userProfileSnap) => {
7474
const {
7575
profileParamsToPopulate,
76-
autoPopulateProfile
76+
autoPopulateProfile,
77+
useFirestoreForProfile
7778
} = firebase._.config
7879
const profile = getProfileFromSnap(userProfileSnap)
7980
if (
8081
!profileParamsToPopulate ||
82+
useFirestoreForProfile || // populating profile through firestore not yet supported
8183
(!isArray(profileParamsToPopulate) &&
8284
!isString(profileParamsToPopulate))
8385
) {
86+
if (useFirestoreForProfile && profileParamsToPopulate) {
87+
console.warn('Profile population is not yet supported for Firestore') // eslint-disable-line no-console
88+
}
8489
dispatch({ type: actionTypes.SET_PROFILE, profile })
8590
} else {
8691
// Convert array of populate config into an array of once query promises
@@ -322,7 +327,11 @@ const handleAuthStateChange = (dispatch, firebase, authData) => {
322327

323328
watchUserProfile(dispatch, firebase)
324329

325-
dispatch({ type: actionTypes.LOGIN, auth: authData })
330+
dispatch({
331+
type: actionTypes.LOGIN,
332+
auth: authData,
333+
preserve: config.preserveOnLogin
334+
})
326335

327336
// Run onAuthStateChanged if it exists in config
328337
if (isFunction(config.onAuthStateChanged)) {
@@ -349,7 +358,11 @@ export const handleRedirectResult = (dispatch, firebase, authData) => {
349358
firebase._.authUid = user.uid // eslint-disable-line no-param-reassign
350359
watchUserProfile(dispatch, firebase)
351360

352-
dispatch({ type: actionTypes.LOGIN, auth: user })
361+
dispatch({
362+
type: actionTypes.LOGIN,
363+
auth: user,
364+
preserve: firebase._.config.preserveOnLogin
365+
})
353366

354367
createUserProfile(dispatch, firebase, user, {
355368
email: user.email,
@@ -422,7 +435,6 @@ export const init = (dispatch, firebase) => {
422435
export const login = (dispatch, firebase, credentials) => {
423436
if (firebase._.config.resetBeforeLogin) {
424437
dispatchLoginError(dispatch, null)
425-
dispatch({ type: actionTypes.UNLOAD_PROFILE })
426438
}
427439

428440
const { method, params } = getLoginMethodAndParams(firebase, credentials)

src/constants.js

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ export const actionTypes = {
6262
REMOVE: `${actionsPrefix}/REMOVE`,
6363
MERGE: `${actionsPrefix}/MERGE`,
6464
SET_PROFILE: `${actionsPrefix}/SET_PROFILE`,
65-
UNLOAD_PROFILE: `${actionsPrefix}/UNLOAD_PROFILE`,
6665
LOGIN: `${actionsPrefix}/LOGIN`,
6766
LOGOUT: `${actionsPrefix}/LOGOUT`,
6867
LOGIN_ERROR: `${actionsPrefix}/LOGIN_ERROR`,

0 commit comments

Comments
 (0)