Higher Order Component (HOC) for using Firebase with React and Redux
react-redux-firebase is the new version of this library
This library will no longer be updated under this name after v1.0.0
, please use react-redux-firebase.
View deployed version of Material Example here
- Integrated into redux
- Population capability (similar to JOIN)
- Support small data ( using
value
) or large datasets ( usingchild_added
,child_removed
,child_changed
) - queries support (
orderByChild
,orderByKey
,orderByValue
,orderByPriority
,limitToLast
,limitToFirst
,startAt
,endAt
,equalTo
right now ) - Automatic binding/unbinding
- Declarative decorator syntax for React components
- Firebase v3+ support
- Support for updating and nested props
- Out of the box support for authentication (with auto load user profile)
- Lots of helper functions
NOTE: redux-firebasev3 has been moved to react-redux-firebase
See API Docs
generator-react-firebase uses react-redux-firebase when opting to include redux
Include reduxFirebase in your store compose function:
import { createStore, combineReducers, compose } from 'redux'
import { reduxFirebase, firebaseStateReducer } from 'react-redux-firebase'
// Add Firebase to reducers
const rootReducer = combineReducers({
firebase: firebaseStateReducer
})
// Firebase config
const config = {
apiKey: '<your-api-key>',
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>'
}
// Add redux Firebase to compose
const createStoreWithFirebase = compose(
reduxFirebase(config, { userProfile: 'users' }),
)(createStore)
// Create store with reducers and initial state
const store = createStoreWithFirebase(rootReducer, initialState)
In components:
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { firebase, helpers } from 'react-redux-firebase'
const { isLoaded, isEmpty, dataToJS } = helpers
// Can be used if firebase is used elsewhere
// import { firebaseConnect } from 'react-redux-firebase'
// @firebaseConnect( [
// '/todos'
// ])
@firebase( [
'/todos'
// { type: 'once', path: '/todos' } // for loading once instead of binding
])
@connect(
({firebase}) => ({
todos: dataToJS(firebase, '/todos'),
})
)
class Todos extends Component {
static propTypes = {
todos: PropTypes.object,
firebase: PropTypes.object
}
render() {
const { firebase, todos } = this.props;
// Add a new todo to firebase
const handleAdd = () => {
const {newTodo} = this.refs
firebase.push('/todos', { text:newTodo.value, done:false })
newTodo.value = ''
}
// Build Todos list if todos exist and are loaded
const todosList = !isLoaded(todos)
? 'Loading'
: isEmpty(todos)
? 'Todo list is empty'
: Object.keys(todos).map(
(key, id) => (
<TodoItem key={key} id={id} todo={todos[key]}/>
)
)
return (
<div>
<h1>Todos</h1>
<ul>
{todosList}
</ul>
<input type="text" ref="newTodo" />
<button onClick={handleAdd}>
Add
</button>
</div>
)
}
}
export default Todos
Alternatively, if you choose not to use decorators:
const wrappedTodos = firebase([
'/todos'
])(Todos)
export default connect(
({firebase}) => ({
todos: dataToJS(firebase, '/todos'),
})
)(wrappedTodos)