Skip to content

Commit 099e83e

Browse files
authored
v2.0.5
v2.0.5
2 parents 4cf6ec9 + c51e01a commit 099e83e

File tree

11 files changed

+202
-34
lines changed

11 files changed

+202
-34
lines changed

.prettierrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
singleQuote: true
2+
semi: false
3+
trailingComma: 'none'

README.md

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ The [Material Example](https://github.com/prescottprue/react-redux-firebase/tree
3030
- Server Side Rendering Support
3131
- [`react-native` support](/docs/recipes/react-native.md) using [native modules](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/react-native.html#native-modules) or [web sdk](/docs/recipes/react-native.md#jsweb)
3232

33-
## Install
33+
## Installation
3434

3535
```bash
3636
npm install --save react-redux-firebase
3737
```
3838

39+
This assumes you are using [npm](https://www.npmjs.com/) as your package manager.
40+
41+
If you're not, you can access the library on [unpkg](https://unpkg.com/redux-firestore@latest/dist/redux-firestore.min.js), download it, or point your package manager to it. Theres more on this in the [Builds section below](#builds).
42+
3943
## Use
4044

4145
Include `reactReduxFirebase` (store enhancer) and `firebaseReducer` (reducer) while creating your redux store:
@@ -58,7 +62,7 @@ const rrfConfig = {
5862
}
5963

6064
// initialize firebase instance
61-
firebase.initializeApp(config) // <- new to v2.*.*
65+
firebase.initializeApp(firebaseConfig)
6266

6367
// initialize firestore
6468
// firebase.firestore() // <- needed if using firestore
@@ -116,7 +120,7 @@ const Todos = ({ firebase }) => {
116120
}
117121

118122
export default withFirebase(Todos)
119-
// or firebaseConnect()(Todos) if attaching listeners
123+
// or firebaseConnect()(Todos)
120124
```
121125

122126
**Load Data (listeners automatically managed on mount/unmount)**
@@ -157,12 +161,10 @@ export default compose(
157161
firebaseConnect([
158162
'todos' // { path: '/todos' } // object notation
159163
]),
160-
connect(
161-
(state) => ({
162-
todos: state.firebase.data.todos,
163-
// profile: state.firebase.profile // load profile
164-
})
165-
)
164+
connect((state) => ({
165+
todos: state.firebase.data.todos,
166+
// profile: state.firebase.profile // load profile
167+
}))
166168
)(Todos)
167169
```
168170

@@ -250,6 +252,14 @@ export default compose(
250252
)(Todos)
251253
```
252254

255+
## Firestore
256+
257+
If you plan to use Firestore, you should checkout [`redux-firestore`][redux-firestore]. It integrates nicely with `react-redux-firebase` and it allows you to run Real Time Database and Firestore along side each other.
258+
259+
`react-redux-firebase` provides the `firestoreConnect` HOC (similar to `firebaseConnect`) for easy setting/unsetting of listeners.
260+
261+
Currently `react-redux-firebase` still handles auth when using [`redux-firestore`][redux-firestore] - The future plan is to also have auth standalone auth library that will allow the developer to choose which pieces they do/do not want.
262+
253263
## [Docs](http://react-redux-firebase.com)
254264
See full documentation at [react-redux-firebase.com](http://react-redux-firebase.com)
255265

@@ -262,11 +272,18 @@ See full documentation at [react-redux-firebase.com](http://react-redux-firebase
262272

263273
## [Examples](examples)
264274

265-
Examples folder is broken into two categories [complete](https://github.com/prescottprue/react-redux-firebase/tree/master/examples/complete) and [snippets](https://github.com/prescottprue/react-redux-firebase/tree/master/examples/snippets). `/complete` contains full applications that can be run as is, while `/snippets` contains small amounts of code to show functionality (dev tools and deps not included).
275+
### Real World Applications
276+
* [fireadmin.io](http://fireadmin.io) - Firebase Instance Management Tool (source [available here](https://github.com/prescottprue/fireadmin))
277+
278+
If you would like a project added to this section please reach out [over gitter][gitter-url]
279+
280+
### [Examples Folder](examples)
281+
282+
Examples folder is broken into two categories [snippets](examples/snippets) and [complete](examples/complete). `/complete` contains full applications that can be run as is, where as `/snippets` contains small amounts of code to highlight specific functionality (dev tools and deps not included).
266283

267284
#### [State Based Query Snippet](examples/snippets/stateBasedQuery)
268285

269-
Snippet showing querying based on data in redux state. One of the most common examples of this is querying based on the current users auth UID.
286+
Snippet showing querying based on data in redux state. One of the more common examples is querying based on the current users auth UID.
270287

271288
#### [Decorators Snippet](examples/snippets/decorators)
272289

@@ -294,17 +311,9 @@ View docs for recipes on integrations with:
294311
* [redux-saga](http://react-redux-firebase.com/docs/integrations/redux-saga.md)
295312
* [redux-form](http://react-redux-firebase.com/docs/integrations/redux-form.md)
296313
* [redux-auth-wrapper](http://react-redux-firebase.com/docs/integrations/routing.md#advanced)
297-
* [redux-persist](http://react-redux-firebase.com/docs/integrations/redux-persist.md) - [improved integration with `v2.0.0`](http://react-redux-firebase.com/docs/integrations/redux-persist.html)
314+
* [redux-persist](http://react-redux-firebase.com/docs/integrations/redux-persist.md)
298315
* [react-native](/docs/integrations/react-native.md)
299-
* [react-native-firebase](http://react-redux-firebase.com/docs/integrations/react-native.html#native-modules) - requires `v2.0.0`
300-
301-
## Firestore
302-
303-
If you plan to use Firestore, you should checkout [`redux-firestore`][redux-firestore]. It integrates nicely with `react-redux-firebase` (v2 only) and it allows you to run Real Time Database and Firestore along side each other.
304-
305-
`react-redux-firebase` provides the `firestoreConnect` HOC (similar to `firebaseConnect`) for easy setting/unsetting of listeners.
306-
307-
Currently `react-redux-firebase` still handles auth when using [`redux-firestore`][redux-firestore] - The future plan is to also have auth standalone auth library that will allow the developer to choose which pieces they do/do not want.
316+
* [react-native-firebase](http://react-redux-firebase.com/docs/integrations/react-native.html#native-modules)
308317

309318
## Starting A Project
310319

@@ -316,10 +325,26 @@ Currently `react-redux-firebase` still handles auth when using [`redux-firestore
316325

317326
The [examples folder](/examples) contains full applications that can be copied/adapted and used as a new project.
318327

319-
### FAQ
328+
## FAQ
320329

321330
Please visit the [FAQ section of the docs](http://docs.react-redux-firebase.com/history/v2.0.0/docs/FAQ.html)
322331

332+
## Builds
333+
334+
Most commonly people consume Redux Firestore as a [CommonJS module](http://webpack.github.io/docs/commonjs.html). This module is what you get when you import redux in a Webpack, Browserify, or a Node environment.
335+
336+
If you don't use a module bundler, it's also fine. The redux-firestore npm package includes precompiled production and development [UMD builds](https://github.com/umdjs/umd) in the [dist folder](https://unpkg.com/redux-firestore@latest/dist/). They can be used directly without a bundler and are thus compatible with many popular JavaScript module loaders and environments. For example, you can drop a UMD build as a `<script>` tag on the page. The UMD builds make Redux Firestore available as a `window.ReduxFirestore` global variable.
337+
338+
It can be imported like so:
339+
340+
```html
341+
<script src="../node_modules/react-redux-firebase/dist/react-redux-firebase.min.js"></script>
342+
<!-- or through cdn: <script src="https://unpkg.com/react-redux-firebase@latest/dist/react-redux-firebase.min.js"></script> -->
343+
<script>console.log('react redux firebase:', window.ReactReduxFirebase)</script>
344+
```
345+
346+
Note: In an effort to keep things simple, the wording from this explanation was modeled after [the installation section of the Redux Docs](https://redux.js.org/#installation).
347+
323348
## Contributors
324349

325350
This project exists thanks to all the people who contribute.

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-redux-firebase",
3-
"version": "2.0.4",
3+
"version": "2.0.5",
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",
@@ -11,7 +11,7 @@
1111
"clean": "rimraf es lib dist coverage",
1212
"lint": "eslint src/** test/unit/** test/setup.js",
1313
"lint:fix": "npm run lint -- --fix",
14-
"format": "prettier --single-quote --no-semi --trailing-comma none --write \"src/**/*.js\" \"test/**/*.js\"",
14+
"format": "prettier --write \"src/**/*.js\" \"test/**/*.js\"",
1515
"test": "mocha -R spec ./test/unit/**",
1616
"test:cov": "istanbul cover ./node_modules/mocha/bin/_mocha ./test/unit/**",
1717
"codecov": "cat coverage/lcov.info | codecov",

src/firestoreConnect.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ export const createFirestoreConnect = (storeKey = 'store') => (
5353
}
5454
}
5555

56-
// TODO: Re-attach listeners on query path change
5756
componentWillReceiveProps(np) {
5857
const { firebase, firestore } = this.store
5958
const inputAsFunc = createCallable(dataOrFn)

src/helpers.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ const buildChildList = (state, list, p) =>
189189
mapValues(list, (val, key) => {
190190
let getKey = val
191191
// Handle key: true lists
192-
if (val === true) {
192+
if (val === true || p.populateByKey) {
193193
getKey = key
194194
}
195195
// Allow for aliasing populated data see #126 for more details
@@ -210,7 +210,7 @@ const buildChildList = (state, list, p) =>
210210
: get(state.data, pathString)
211211
}
212212
// Populate child does not exist
213-
return val === true ? val : getKey
213+
return val === true || p.populateByKey ? val : getKey
214214
})
215215

216216
/**

src/utils/populate.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export const populateList = (firebase, list, p, results) => {
108108
return Promise.all(
109109
map(list, (id, childKey) => {
110110
// handle list of keys
111-
const populateKey = id === true ? childKey : id
111+
const populateKey = id === true || p.populateByKey ? childKey : id
112112
return getPopulateChild(firebase, p, populateKey).then(pc => {
113113
if (pc) {
114114
// write child to result object under root name if it is found

test/mockData.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export const exampleData = {
2525
collaborators: {
2626
ABC: true,
2727
abc: true
28+
},
29+
nonKeyTrue: {
30+
ABC: 10,
31+
abc: 'testing'
2832
}
2933
},
3034
QRS: {
@@ -77,6 +81,10 @@ export const exampleData = {
7781
tester: {
7882
somePermission: true
7983
}
84+
},
85+
nonKeyTrue: {
86+
ABC: 10,
87+
abc: 'testing'
8088
}
8189
},
8290
ordered: {

test/unit/actions/auth.spec.js

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
confirmPasswordReset,
1818
verifyPasswordResetCode
1919
} from '../../../src/actions/auth'
20+
import { cloneDeep } from 'lodash'
2021
import { actionTypes } from '../../../src/constants'
2122
import {
2223
fakeFirebase,
@@ -50,7 +51,11 @@ const addSpyWithArgsToAuthMethod = (methodName, spyFunc, args = []) => ({
5051
[methodName]: () => spyFunc(args)
5152
})
5253
})
53-
const fakeLogin = { email: '[email protected]', password: 'asdfasdf', role: 'admin' }
54+
const fakeLogin = {
55+
56+
password: 'asdfasdf',
57+
role: 'admin'
58+
}
5459

5560
describe('Actions: Auth -', () => {
5661
beforeEach(() => {
@@ -72,6 +77,19 @@ describe('Actions: Auth -', () => {
7277
unWatchUserProfile(fakeFirebase)
7378
expect(fakeFirebase._.profileWatch).to.equal(null)
7479
})
80+
81+
it('calls profile watch then sets to null when useFirestoreForProfile: true', () => {
82+
let profileCalled
83+
let currentFake = cloneDeep(fakeFirebase)
84+
currentFake._.profileWatch = () => {
85+
profileCalled = true
86+
}
87+
currentFake._.config.useFirestoreForProfile = true
88+
currentFake.firestore = {}
89+
unWatchUserProfile(currentFake)
90+
expect(currentFake._.profileWatch).to.equal(null)
91+
expect(profileCalled).to.equal(true)
92+
})
7593
})
7694

7795
describe('handleProfileWatchResponse -', () => {
@@ -82,7 +100,46 @@ describe('Actions: Auth -', () => {
82100
profile = { email: '[email protected]' }
83101
profileSnap = { val: () => profile }
84102
})
103+
104+
describe('dispatches SET_PROFILE with profile', () => {
105+
it('from RTDB data', () => {
106+
firebase._.config.profileParamsToPopulate = undefined
107+
handleProfileWatchResponse(dispatchSpy, firebase, profileSnap)
108+
expect(dispatchSpy).to.be.calledWith({
109+
type: actionTypes.SET_PROFILE,
110+
profile
111+
})
112+
})
113+
114+
it('from Firestore data', () => {
115+
firebase._.config.profileParamsToPopulate = undefined
116+
const firestoreProfileSnap = { data: () => profile, exists: true }
117+
handleProfileWatchResponse(dispatchSpy, firebase, firestoreProfileSnap)
118+
expect(dispatchSpy).to.be.calledWith({
119+
type: actionTypes.SET_PROFILE,
120+
profile
121+
})
122+
})
123+
124+
it('that is an empty object (sets profile to null)', () => {
125+
firebase._.config.profileParamsToPopulate = undefined
126+
handleProfileWatchResponse(dispatchSpy, firebase, {})
127+
expect(dispatchSpy).to.be.calledWith({
128+
type: actionTypes.SET_PROFILE,
129+
profile: null
130+
})
131+
})
132+
})
133+
85134
describe('profileParamsToPopulate setting -', () => {
135+
let consoleWarnSpy
136+
137+
beforeEach(() => {
138+
consoleWarnSpy = sinon.spy(console, 'warn')
139+
})
140+
afterEach(() => {
141+
consoleWarnSpy.restore()
142+
})
86143
it('undefined - dispatches SET_PROFILE with profile', () => {
87144
firebase._.config.profileParamsToPopulate = undefined
88145
handleProfileWatchResponse(dispatchSpy, firebase, profileSnap)
@@ -109,6 +166,18 @@ describe('Actions: Auth -', () => {
109166
// expect(dispatchSpy)
110167
// .to.be.calledWith({ type: actionTypes.SET_PROFILE })
111168
})
169+
170+
it('Any when useFirestoreForProfile: true - calls console.warn', () => {
171+
let currentFake = cloneDeep(fakeFirebase)
172+
currentFake._.profileWatch = () => {}
173+
currentFake._.config.useFirestoreForProfile = true
174+
currentFake._.config.profileParamsToPopulate = ['some']
175+
currentFake.firestore = {}
176+
handleProfileWatchResponse(dispatchSpy, currentFake)
177+
expect(consoleWarnSpy).to.be.calledWith(
178+
'Profile population is not yet supported for Firestore'
179+
)
180+
})
112181
})
113182
})
114183

0 commit comments

Comments
 (0)