Skip to content

Commit 3b29191

Browse files
authored
v2.0.0-beta.11 (#295)
* fix(populate): missing childKey causes no population - #277 (thanks @JeremyPlease) * feat(firestore): `firestoreConnect` - React HOC that sets listeners to Cloud Firestore (similar to `firebaseConnect`, but for Cloud Firestore instead of Real Time Database) - #286 * feat(firestore): `firestoreReducer` is exported from [`redux-firestore`](https://github.com/prescottprue/redux-firestore) included to handle managing `firestore` state - #286 * feat(core): `withFirebase` - React HOC for just passing `props.firebase` (`firebaseConnect` without any listener management) * feat(docs): Firestore page added to docs (outlining usage of `firestoreConnect` and `setListener`) * feat(examples): Firestore complete example added * feat(docs): README and Query examples simplified + improved * feat(docs): FAQ moved to its own docs page **NOTE**: After the Firestore API (including `firestoreConnect`) is stabilized, the `v2.0.0` pre-releases should be ready for release candidate status (pending other major bugs).
1 parent 2fc118f commit 3b29191

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1654
-503
lines changed

.eslintrc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ env:
1111
jasmine: true
1212
node: true
1313

14-
ecmaFeatures:
15-
jsx: true
16-
modules: true
17-
1814
rules:
1915
semi: [2, 'never']
2016
no-console: 'error'

README.md

Lines changed: 122 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
[![License][license-image]][license-url]
99
[![Build Status][travis-image]][travis-url]
1010
[![Dependency Status][daviddm-image]][daviddm-url]
11-
[![Backers on Open Collective][backers]](#backers)
1211

1312
[![Gitter][gitter-image]][gitter-url]
1413

@@ -20,14 +19,13 @@
2019
The [Material Example](https://github.com/prescottprue/react-redux-firebase/tree/master/examples/complete/material) is deployed to [demo.react-redux-firebase.com](https://demo.react-redux-firebase.com).
2120

2221
## Features
23-
- Integrated into redux
2422
- Support for updating and nested props
2523
- [Population capability](http://react-redux-firebase.com/docs/populate) (similar to mongoose's `populate` or SQL's `JOIN`)
2624
- Out of the box support for authentication (with auto load user profile)
27-
- Firebase Storage Support
25+
- Firebase Database, Firestore, Auth, Storage, and Messaging Support
2826
- Support small data ( using `value` ) or large datasets ( using `child_added`, `child_removed`, `child_changed` )
29-
- queries support ( `orderByChild`, `orderByKey`, `orderByValue`, `orderByPriority`, `limitToLast`, `limitToFirst`, `startAt`, `endAt`, `equalTo` right now )
30-
- Automatic binding/unbinding
27+
- queries including `orderByChild`, `orderByKey`, `orderByValue`, `orderByPriority`, `limitToLast`, `limitToFirst`, `startAt`, `endAt`, `equalTo`
28+
- Automatic binding/unbinding through `firestoreConnect` (manual through `watchEvent`)
3129
- Declarative decorator syntax for React components
3230
- Tons of integrations including [`redux-thunk`](https://github.com/gaearon/redux-thunk) and [`redux-observable`](https://redux-observable.js.org/)
3331
- Action Types and other Constants exported for external use (such as in `redux-observable`)
@@ -41,39 +39,38 @@ The [Material Example](https://github.com/prescottprue/react-redux-firebase/tree
4139
npm install --save react-redux-firebase
4240
```
4341

44-
#### Other Versions
45-
46-
The above install command will install the `@latest` tag. You may also use the following tags when installing to get different versions:
47-
48-
* `@next` - Most possible up to date code. Currently, points to active progress with `v2.0.0-*` pre-releases. *Warning:* Syntax is different than current stable version.
49-
50-
Be aware of changes when using a version that is not tagged `@latest`. Please report any issues you encounter, and try to keep an eye on the [releases page](https://github.com/prescottprue/react-redux-firebase/releases) for updates.
51-
5242
## Use
5343

54-
**Note:** If you are just starting a new project, you may want to use [`v2.0.0`](http://docs.react-redux-firebase.com/history/v2.0.0/#use) since it has an even easier syntax. For clarity on the transition, view the [`v1` -> `v2` migration guide](http://docs.react-redux-firebase.com/history/v2.0.0/docs/v2-migration-guide.html)
55-
5644
Include `reactReduxFirebase` in your store compose function and `firebaseStateReducer` in your reducers:
5745

5846
```javascript
5947
import { createStore, combineReducers, compose } from 'redux'
6048
import { reactReduxFirebase, firebaseStateReducer } from 'react-redux-firebase'
6149
import firebase from 'firebase'
50+
// import 'firebase/firestore' // add this to use firestore
6251

6352
const firebaseConfig = {
6453
apiKey: '<your-api-key>',
6554
authDomain: '<your-auth-domain>',
6655
databaseURL: '<your-database-url>',
6756
storageBucket: '<your-storage-bucket>'
6857
}
69-
const rrfConfig = { userProfile: 'users' } // react-redux-firebase config
58+
59+
// react-redux-firebase config
60+
const rrfConfig = {
61+
userProfile: 'users',
62+
// useFirestoreForProfile: true // Firestore for Profile instead of Realtime DB
63+
}
7064

7165
// initialize firebase instance
72-
const firebaseApp = firebase.initializeApp(config) // <- new to v2.*.*
66+
firebase.initializeApp(config) // <- new to v2.*.*
7367

74-
// Add reduxReduxFirebase to compose
68+
// initialize firestore
69+
// firebase.firestore() // <- only needed if using firestore
70+
71+
// Add reduxReduxFirebase enhancer when making store creator
7572
const createStoreWithFirebase = compose(
76-
reactReduxFirebase(firebaseApp, rrfConfig), // firebase instance as first argument
73+
reactReduxFirebase(firebase, rrfConfig), // firebase instance as first argument
7774
)(createStore)
7875

7976
// Add Firebase to reducers
@@ -88,122 +85,123 @@ const store = createStoreWithFirebase(rootReducer, initialState)
8885

8986
In components:
9087

91-
```javascript
92-
import React, { Component } from 'react'
88+
**Add Data**
89+
90+
```jsx
91+
import React from 'react'
92+
import PropTypes from 'prop-types'
93+
import { withFirebase } from 'react-redux-firebase'
94+
95+
const Todos = ({ firebase }) => {
96+
const sampleTodo = { text: 'Sample', done: false }
97+
const pushSample = () => firebase.push('todos', sampleTodo)
98+
return (
99+
<div>
100+
<h1>Todos</h1>
101+
<ul>
102+
{todosList}
103+
</ul>
104+
<input type="text" ref="newTodo" />
105+
<button onClick={pushSample}>
106+
Add
107+
</button>
108+
</div>
109+
)
110+
}
111+
112+
export default withFirebase(Todos)
113+
// or firebaseConnect()(Todos) if attaching listeners
114+
```
115+
116+
**Load Data (listeners managed on mount/unmount)**
117+
118+
```jsx
119+
import React from 'react'
93120
import PropTypes from 'prop-types'
94121
import { connect } from 'react-redux'
95122
import { compose } from 'redux'
96123
import { firebaseConnect, isLoaded, isEmpty } from 'react-redux-firebase'
97124

98-
class Todos extends Component {
99-
static propTypes = {
100-
todos: PropTypes.object,
101-
auth: PropTypes.object,
102-
firebase: PropTypes.object
103-
}
104-
105-
addTodo = () => {
106-
const { newTodo } = this.refs
107-
return this.props.firebase
108-
.push('/todos', { text: newTodo.value, done: false })
109-
.then(() => {
110-
newTodo.value = ''
111-
console.log('Todo Created!')
112-
})
113-
.catch((err) => {
114-
console.log('Error creating todo:', err) // error is also set to state.firebase.authError
115-
})
116-
}
117-
118-
render() {
119-
const { todos } = this.props;
120-
121-
// Build Todos list if todos exist and are loaded
122-
const todosList = !isLoaded(todos)
123-
? 'Loading'
124-
: isEmpty(todos)
125-
? 'Todo list is empty'
126-
: Object.keys(todos).map(
127-
(key, id) => (
128-
<TodoItem key={key} id={id} todo={todos[key]}/>
129-
)
125+
const Todos = ({ todos, firebase }) => {
126+
// Build Todos list if todos exist and are loaded
127+
const todosList = !isLoaded(todos)
128+
? 'Loading'
129+
: isEmpty(todos)
130+
? 'Todo list is empty'
131+
: Object.keys(todos).map(
132+
(key, id) => (
133+
<TodoItem key={key} id={id} todo={todos[key]}/>
130134
)
131-
132-
return (
133-
<div>
134-
<h1>Todos</h1>
135-
<ul>
136-
{todosList}
137-
</ul>
138-
<input type="text" ref="newTodo" />
139-
<button onClick={this.handleAdd}>
140-
Add
141-
</button>
142-
</div>
143-
)
144-
}
135+
)
136+
return (
137+
<div>
138+
<h1>Todos</h1>
139+
<ul>
140+
{todosList}
141+
</ul>
142+
<input type="text" ref="newTodo" />
143+
<button onClick={this.handleAdd}>
144+
Add
145+
</button>
146+
</div>
147+
)
145148
}
146149

147150
export default compose(
148151
firebaseConnect([
149-
'/todos' // { path: '/todos' } // object notation
152+
'todos' // { path: '/todos' } // object notation
150153
]),
151154
connect(
152-
({ firebase: { data: { todos } } }) => ({ // state.firebase.data.todos
153-
todos // Connect props.todos to state.firebase.data.todos
155+
(state) => ({
156+
todos: state.firebase.data.todos,
157+
// profile: state.firebase.profile // load profile
154158
})
155159
)
156160
)(Todos)
157161
```
158162

159-
Alternatively, if you choose to use decorators:
160-
161-
```javascript
162-
@firebaseConnect([
163-
'/todos' // { path: '/todos' } // object notation
164-
])
165-
@connect(
166-
({ firebase: { data: { todos } } }) => ({
167-
todos // Connect props.todos to state.firebase.data.todos
168-
})
169-
)
170-
export default class Todos extends Component {
171-
// component code
172-
}
173-
```
174-
175-
### Decorators
176-
177-
Though they are optional, it is highly recommended that you use decorators with this library. [The Simple Example](examples/simple) shows implementation without decorators, while [the Decorators Example](examples/decorators) shows the same application with decorators implemented.
178-
179-
A side by side comparison using [react-redux](https://github.com/reactjs/react-redux)'s `connect` function/HOC is the best way to illustrate the difference:
180-
181-
#### Without Decorators
182-
```javascript
183-
class SomeComponent extends Component {
163+
**Load Data On Click**
184164

165+
```jsx
166+
import React from 'react'
167+
import PropTypes from 'prop-types'
168+
import { connect } from 'react-redux'
169+
import { compose } from 'redux'
170+
import { withFirebase, isLoaded, isEmpty } from 'react-redux-firebase'
171+
172+
const Todos = ({ firebase }) => {
173+
// Build Todos list if todos exist and are loaded
174+
const todosList = !isLoaded(todos)
175+
? 'Loading'
176+
: isEmpty(todos)
177+
? 'Todo list is empty'
178+
: Object.keys(todos).map(
179+
(key, id) => <TodoItem key={key} id={id} todo={todos[key]}/>
180+
)
181+
return (
182+
<div>
183+
<h1>Todos</h1>
184+
<ul>
185+
{todosList}
186+
</ul>
187+
<button onClick={() => firebase.watchEvent('value', 'todos')}>
188+
Load Todos
189+
</button>
190+
</div>
191+
)
185192
}
186-
export default connect()(SomeComponent)
187-
```
188-
vs.
189-
190-
#### With Decorators
191-
```javascript
192-
@connect()
193-
export default class SomeComponent extends Component {
194193

195-
}
194+
export default compose(
195+
withFirebase, // or firebaseConnect()
196+
connect(
197+
(state) => ({
198+
todos: state.firebase.data.todos,
199+
// profile: state.firebase.profile // load profile
200+
})
201+
)
202+
)(Todos)
196203
```
197204

198-
To enable this functionality, you will most likely need to install a plugin (depending on your build setup). For Webpack and Babel, you will need to make sure you have installed and enabled [babel-plugin-transform-decorators-legacy](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy) by doing the following:
199-
200-
1. run `npm i --save-dev babel-plugin-transform-decorators-legacy`
201-
2. Add the following line to your `.babelrc`:
202-
```json
203-
{
204-
"plugins": ["transform-decorators-legacy"]
205-
}
206-
```
207205

208206
## [Docs](http://react-redux-firebase.com)
209207
See full documentation at [react-redux-firebase.com](http://react-redux-firebase.com)
@@ -242,14 +240,15 @@ Join us on the [redux-firebase gitter](https://gitter.im/redux-firebase/Lobby).
242240

243241
View docs for recipes on integrations with:
244242

245-
* [redux-thunk](/docs/recipes/thunks.md)
246-
* [redux-observable](/docs/recipes/epics.md)
247-
* [redux-saga](/docs/recipes/redux-saga.md)
248-
* [redux-form](/docs/recipes/redux-form.md)
249-
* [redux-auth-wrapper](/docs/recipes/routing.md#advanced)
250-
* [redux-persist](/docs/recipes/redux-persist.md) - [improved integration with `v2.0.0`](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/redux-persist.html)
251-
* [react-native](/docs/recipes/react-native.md)
252-
* [react-native-firebase](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/react-native.html#native-modules) - requires `v2.0.0`
243+
* [redux-firestore](/docs/firestore.md)
244+
* [redux-thunk](/docs/integrations/thunks.md)
245+
* [redux-observable](/docs/integrations/epics.md)
246+
* [redux-saga](/docs/integrations/redux-saga.md)
247+
* [redux-form](/docs/integrations/redux-form.md)
248+
* [redux-auth-wrapper](/docs/integrations/routing.md#advanced)
249+
* [redux-persist](/docs/integrations/redux-persist.md) - [improved integration with `v2.0.0`](http://docs.react-redux-firebase.com/history/v2.0.0/docs/integrations/redux-persist.html)
250+
* [react-native](/docs/integrations/react-native.md)
251+
* [react-native-firebase](http://docs.react-redux-firebase.com/history/v2.0.0/docs/integrations/react-native.html#native-modules) - requires `v2.0.0`
253252

254253
## Starting A Project
255254

@@ -261,47 +260,9 @@ View docs for recipes on integrations with:
261260

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

264-
## FAQ
265-
266-
1. How is this different than [`redux-react-firebase`](https://github.com/tiberiuc/redux-react-firebase)?
267-
268-
This library was actually originally forked from redux-react-firebase, but adds extended functionality such as:
269-
* [populate functionality](http://react-redux-firebase.com/docs/populate) (similar to mongoose's `populate` or SQL's `JOIN`)
270-
* `react-native` support ([web/js](http://react-redux-firebase.com/docs/recipes/react-native.html) or native modules through [`react-native-firebase`](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/react-native.html#native-modules))
271-
* tons of [integrations](#integrations)
272-
* [`profileFactory`](http://react-redux-firebase.com/docs/config) - change format of profile stored on Firebase
273-
* [`getFirebase`](http://react-redux-firebase.com/docs/thunks) - access to firebase instance that fires actions when methods are called
274-
* [access to firebase's `storage`](http://react-redux-firebase.com/docs/storage) and `messaging` services
275-
* `uniqueSet` method helper for only setting if location doesn't already exist
276-
* Object or String notation for paths (`[{ path: '/todos' }]` equivalent to `['/todos']`)
277-
* Action Types and other Constants are exposed for external usage (such as with `redux-observable`)
278-
* Server Side Rendering Support
279-
* [Complete Firebase Auth Integration](http://react-redux-firebase.com/docs/auth.html#examples) including `signInWithRedirect` compatibility for OAuth Providers
280-
281-
#### Well why not combine?
282-
I have been talking to the author of [redux-react-firebase](https://github.com/tiberiuc/redux-react-firebase) about combining, but we are not sure that the users of both want that at this point. Join us on the [redux-firebase gitter](https://gitter.im/redux-firebase/Lobby) if you haven't already since a ton of this type of discussion goes on there.
283-
284-
#### What about [redux-firebase](https://github.com/colbyr/redux-firebase)?
285-
The author of [redux-firebase](https://github.com/colbyr/redux-firebase) has agreed to share the npm namespace! Currently the plan is to take the framework agnostic redux core logic of `react-redux-firebase` and [place it into `redux-firebase`](https://github.com/prescottprue/redux-firebase)). Eventually `react-redux-firebase` and potentially other framework libraries can depend on that core (the new `redux-firebase`).
286-
287-
2. Why use redux if I have Firebase to store state?
288-
289-
This isn't a super quick answer, so I wrote up [a medium article to explain](https://medium.com/@prescottprue/firebase-with-redux-82d04f8675b9)
290-
291-
3. Where can I find some examples?
292-
293-
* [Recipes Section](http://react-redux-firebase.com/docs/recipes/) of [the docs](http://react-redux-firebase.com/docs/recipes/)
294-
* [examples folder](/examples) contains [complete example apps](/examples/complete) as well as [useful snippets](/examples/snippets)
295-
296-
4. How does `connect` relate to `firebaseConnect`?
297-
298-
![data flow](/docs/static/dataFlow.png)
299-
300-
5. How do I help?
263+
### FAQ
301264

302-
* Join the conversion on [gitter][gitter-url]
303-
* Post Issues
304-
* Create Pull Requests
265+
Please visit the [FAQ section of the docs](http://docs.react-redux-firebase.com/history/v2.0.0/docs/FAQ.html)
305266

306267
## Contributors
307268

0 commit comments

Comments
 (0)