Skip to content

Commit 5975db1

Browse files
author
Scott Prue
committed
Readme updated with v1.5.0 and v2.0.0 links.
1 parent 0ad5b10 commit 5975db1

File tree

2 files changed

+126
-198
lines changed

2 files changed

+126
-198
lines changed

README.md

Lines changed: 98 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
[![Code Style][code-style-image]][code-style-url]
1010

1111
[![Gitter][gitter-image]][gitter-url]
12-
[<img src="http://npm.packagequality.com/badge/react-redux-firebase.png" align="right"/>](http://packagequality.com/#?package=react-redux-firebase)
12+
[<img src="http://npm.packagequality.com/badge/react-redux-firebase.png" align="right"/>](https://packagequality.com/#?package=react-redux-firebase)
1313

1414
> Redux bindings for Firebase. Includes Higher Order Component (HOC) for use with React.
1515
@@ -27,60 +27,29 @@ The [Material Example](https://github.com/prescottprue/react-redux-firebase/tree
2727
- queries support ( `orderByChild`, `orderByKey`, `orderByValue`, `orderByPriority`, `limitToLast`, `limitToFirst`, `startAt`, `endAt`, `equalTo` right now )
2828
- Automatic binding/unbinding
2929
- Declarative decorator syntax for React components
30-
- [`redux-thunk`](https://github.com/gaearon/redux-thunk) and [`redux-observable`](https://redux-observable.js.org/) integrations
30+
- Tons of integrations including [`redux-thunk`](https://github.com/gaearon/redux-thunk) and [`redux-observable`](https://redux-observable.js.org/)
3131
- Action Types and other Constants exported for external use (such as in `redux-observable`)
3232
- Firebase v3+ support
3333
- Server Side Rendering Support
34-
- [`react-native` support](/docs/recipes/react-native.md)
34+
- [`react-native` support](/docs/recipes/react-native.md) using [native modules](/docs/recipes/react-native.md#native-modules) or [web sdk](/docs/recipes/react-native.md#jsweb)
3535

3636
## Install
37+
3738
```bash
3839
npm install --save react-redux-firebase
3940
```
41+
#### Other Versions
4042

41-
## Before Use
42-
43-
### Peer Dependencies
44-
45-
Install peer dependencies: `npm i --save redux react-redux`
46-
47-
### Decorators
48-
49-
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.
50-
51-
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:
43+
The above install command will install the `@latest` tag. You may also use the following tags when installing to get different versions:
5244

53-
#### Without Decorators
54-
```javascript
55-
class SomeComponent extends Component {
45+
<!-- `@next` - Next upcoming release. currently points to active progress with `v1.5.0-*` pre-releases -->
46+
`@canary` - 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.
5647

57-
}
58-
export default connect()(SomeComponent)
59-
```
60-
vs.
61-
62-
#### With Decorators
63-
```javascript
64-
@connect()
65-
export default class SomeComponent extends Component {
66-
67-
}
68-
```
69-
70-
In order 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:
71-
72-
1. run `npm i --save-dev babel-plugin-transform-decorators-legacy`
73-
2. Add the following line to your `.babelrc`:
74-
```
75-
{
76-
"plugins": ["transform-decorators-legacy"]
77-
}
78-
```
48+
**Note:** Be careful using no-stable versions. Try to keep an eye on the [releases page](https://github.com/prescottprue/react-redux-firebase/releases) for relevant release info.
7949

8050
## Use
8151

82-
Include reduxFirebase in your store compose function:
83-
52+
Include `reactReduxFirebase` in your store compose function and `firebaseStateReducer` in your reducers:
8453

8554
```javascript
8655
import { createStore, combineReducers, compose } from 'redux'
@@ -109,41 +78,42 @@ const store = createStoreWithFirebase(rootReducer, initialState)
10978
```
11079

11180
In components:
81+
11282
```javascript
113-
import React, { Component, PropTypes } from 'react'
83+
import React, { Component } from 'react'
84+
import PropTypes from 'prop-types' // can also come from react if react <= 15.4.0
11485
import { connect } from 'react-redux'
86+
import { compose } from 'redux'
11587
import {
11688
firebaseConnect,
11789
isLoaded,
11890
isEmpty,
119-
dataToJS
91+
dataToJS,
92+
pathToJS
12093
} from 'react-redux-firebase'
12194

122-
@firebaseConnect([
123-
'/todos'
124-
// { path: '/todos' } // object notation
125-
])
126-
@connect(
127-
({ firebase }) => ({
128-
// Connect todos prop to firebase todos
129-
todos: dataToJS(firebase, '/todos'),
130-
})
131-
)
132-
export default class Todos extends Component {
95+
class Todos extends Component {
13396
static propTypes = {
13497
todos: PropTypes.object,
98+
auth: PropTypes.object,
13599
firebase: PropTypes.object
136100
}
137101

138-
render() {
139-
const { firebase, todos } = this.props;
102+
addTodo = () => {
103+
const { newTodo } = this.refs
104+
return this.props.firebase
105+
.push('/todos', { text: newTodo.value, done: false })
106+
.then(() => {
107+
newTodo.value = ''
108+
console.log('Todo Created!')
109+
})
110+
.catch((err) => {
111+
console.log('Error creating todo:', err) // error is also set to authError
112+
})
113+
}
140114

141-
// Add a new todo to firebase
142-
const handleAdd = () => {
143-
const {newTodo} = this.refs
144-
firebase.push('/todos', { text:newTodo.value, done:false })
145-
newTodo.value = ''
146-
}
115+
render() {
116+
const { todos } = this.props;
147117

148118
// Build Todos list if todos exist and are loaded
149119
const todosList = !isLoaded(todos)
@@ -163,38 +133,75 @@ export default class Todos extends Component {
163133
{todosList}
164134
</ul>
165135
<input type="text" ref="newTodo" />
166-
<button onClick={handleAdd}>
136+
<button onClick={this.handleAdd}>
167137
Add
168138
</button>
169139
</div>
170140
)
171141
}
172142
}
173-
```
174-
175-
Alternatively, if you choose not to use decorators:
176-
177-
```javascript
178-
import { compose } from 'redux'
179143

180144
export default compose(
181-
firebaseConnect(['/todos']),
145+
firebaseConnect([
146+
'todos' // { path: 'todos' } // object notation
147+
]),
182148
connect(
183-
({firebase}) => ({ todos: dataToJS(firebase, '/todos') })
149+
({ firebase } }) => ({ // state.firebase
150+
todos: dataToJS(firebase, 'todos'),
151+
auth: pathToJS(firebase, 'auth')
152+
})
184153
)
185154
)(Todos)
155+
```
156+
157+
Alternatively, if you choose to use decorators:
186158

159+
```javascript
160+
@firebaseConnect([
161+
'todos' // { path: 'todos' } // object notation
162+
])
163+
@connect(
164+
({ firebase }) => ({
165+
todos: dataToJS(firebase, 'todos'),
166+
auth: pathToJS(firebase, 'auth')
167+
})
168+
)
169+
export default class Todos extends Component {
170+
171+
}
187172
```
188173

189-
## Server Side Rendering
174+
### Decorators
190175

191-
Firebase's library requires XML request capability, so if you are using `react-redux-firebase` in a Server Side rendering environment, make sure you require `xmlhttprequest`.
176+
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.
192177

193-
If you disagree with having to do this yourself, hop [on gitter](https://gitter.im/redux-firebase/Lobby) and let us know!
178+
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:
179+
180+
#### Without Decorators
181+
```javascript
182+
class SomeComponent extends Component {
183+
184+
}
185+
export default connect()(SomeComponent)
186+
```
187+
vs.
188+
189+
#### With Decorators
190+
```javascript
191+
@connect()
192+
export default class SomeComponent extends Component {
193+
194+
}
195+
```
196+
197+
In order 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:
194198

195-
```js
196-
// needed to fix "Error: The XMLHttpRequest compatibility library was not found."
197-
global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
199+
1. run `npm i --save-dev babel-plugin-transform-decorators-legacy`
200+
2. Add the following line to your `.babelrc`:
201+
```json
202+
{
203+
"plugins": ["transform-decorators-legacy"]
204+
}
198205
```
199206

200207
## [Docs](http://react-redux-firebase.com)
@@ -206,6 +213,11 @@ See full documentation at [react-redux-firebase.com](http://react-redux-firebase
206213
* [Populate](http://react-redux-firebase.com/docs/populate)
207214
* [API Reference](http://react-redux-firebase.com/docs/api)
208215

216+
#### Other Versions
217+
218+
Other versions docs are available using the dropdown on the above docs link. For quick access:
219+
* [Version `2.0.0` Docs](http://docs.react-redux-firebase.com/history/v2.0.0/)
220+
209221
## [Examples](examples)
210222

211223
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).
@@ -230,118 +242,17 @@ An example that user Material UI built on top of the output of [create-react-app
230242

231243
Join us on the [redux-firebase gitter](https://gitter.im/redux-firebase/Lobby).
232244

233-
## Using With Other Libraries
234-
235-
### redux-thunk
236-
If you are using `redux-thunk`, make sure to set up your thunk middleware using it's redux-thunk's `withExtraArgument` method so that firebase is available within your actions. Here is an example `createStore` function that adds `getFirebase` as third argument along with a thunk that uses it:
237-
238-
createStore:
239-
240-
```javascript
241-
import { applyMiddleware, compose, createStore } from 'redux';
242-
import thunk from 'redux-thunk';
243-
import { reactReduxFirebase, getFirebase } from 'react-redux-firebase';
244-
import makeRootReducer from './reducers';
245-
246-
const fbConfig = {} // your firebase config
247-
const config = {
248-
userProfile: 'users',
249-
enableLogging: false
250-
}
251-
const store = createStore(
252-
makeRootReducer(),
253-
initialState,
254-
compose(
255-
applyMiddleware([
256-
thunk.withExtraArgument(getFirebase) // Pass getFirebase function as extra argument
257-
]),
258-
reactReduxFirebase(fbConfig, config)
259-
)
260-
);
261-
262-
```
263-
Action:
264-
265-
```javascript
266-
import { pathToJS } from 'react-redux-firebase'
267-
268-
export const addTodo = (newTodo) =>
269-
(dispatch, getState, getFirebase) => {
270-
const auth = pathToJS(getState.firebase, 'auth')
271-
newTodo.createdBy = auth.uid //
272-
getFirebase()
273-
.push('todos', newTodo)
274-
// using pushWithMeta instead would attach createdBy and createdAt automatically
275-
.then(() => {
276-
dispatch({
277-
type: 'TODO_CREATED',
278-
payload: newTodo
279-
})
280-
})
281-
};
282-
283-
```
284-
285-
### redux-observable
286-
If you are using `redux-observable`, make sure to set up your redux-observable middleware so that firebase is available within your epics. Here is an example `combineEpics` function that adds `getFirebase` as third argument along with an epic that uses it:
287-
288-
```javascript
289-
import { getFirebase } from 'react-redux-firebase'
290-
import { combineEpics } from 'redux-observable'
291-
292-
const rootEpic = (...args) =>
293-
combineEpics(somethingEpic, epic2)(..args, getFirebase)
294-
295-
// then later in your epics
296-
const somethingEpic = (action$, store, getFirebase) =>
297-
action$.ofType(SOMETHING)
298-
.map(() =>
299-
getFirebase().push('somePath/onFirebase', { some: 'data' })
300-
)
301-
```
302-
303-
### redux-auth-wrapper
304-
305-
*For full example, go to the [Routing Recipes Section of the docs](http://react-redux-firebase.com/docs/recipes/routing.html)*
245+
## Integrations
306246

307-
In order to only allow authenticated users to view a page, a `UserIsAuthenticated` Higher Order Component can be created:
247+
View docs for recipes on integrations with:
308248

309-
```javascript
310-
import { browserHistory } from 'react-router'
311-
import { UserAuthWrapper } from 'redux-auth-wrapper'
312-
import { pathToJS } from 'react-redux-firebase'
313-
314-
export const UserIsAuthenticated = UserAuthWrapper({
315-
wrapperDisplayName: 'UserIsAuthenticated',
316-
authSelector: ({ firebase }) => pathToJS(firebase, 'auth'),
317-
authenticatingSelector: ({ firebase }) =>
318-
pathToJS(firebase, 'isInitializing') === true ||
319-
pathToJS(firebase, 'auth') === undefined
320-
predicate: auth => auth !== null,
321-
redirectAction: (newLoc) => (dispatch) => {
322-
browserHistory.replace(newLoc)
323-
dispatch({
324-
type: 'UNAUTHED_REDIRECT',
325-
payload: { message: 'You must be authenticated.' },
326-
})
327-
},
328-
})
329-
```
330-
331-
Then it can be used as a Higher Order Component wrapper on a component:
332-
333-
```javascript
334-
@UserIsAuthenticated // redirects to '/login' if user not is logged in
335-
export default class ProtectedThing extends Component {
336-
render() {
337-
return (
338-
<div>
339-
You are authed!
340-
</div>
341-
)
342-
}
343-
}
344-
```
249+
* [redux-thunk](/docs/recipes/thunks.md)
250+
* [redux-form](/docs/recipes/redux-form.md)
251+
* [redux-observable](/docs/recipes/redux-observable.md)
252+
* [redux-auth-wrapper](/docs/recipes/routing.md#advanced)
253+
* [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)
254+
* [react-native](/docs/recipes/react-native.md)
255+
* [react-native-firebase](http://docs.react-redux-firebase.com/history/v2.0.0/docs/recipes/react-native.html#native-modules) - requires `v2.0.0`
345256

346257
## Starting A Project
347258

@@ -396,13 +307,6 @@ Meet some of the outstanding companies and individuals that made it possible:
396307

397308
* [Reside Network Inc.](https://github.com/reside-eng)
398309

399-
400-
## Contributors
401-
- [Prescott Prue](https://github.com/prescottprue)
402-
- [Bojhan](https://github.com/Bojhan)
403-
- [Rahav Lussto](https://github.com/RahavLussato)
404-
- [Justin Handley](https://github.com/justinhandley)
405-
406310
## Thanks
407311

408312
Special thanks to [Tiberiu Craciun](https://github.com/tiberiuc) for creating [redux-react-firebase](https://github.com/tiberiuc/redux-react-firebase), which this project was originally based on.

0 commit comments

Comments
 (0)