Redux bindings for Firebase. Includes Higher Order Component (HOC) for use with React.
The Material Example is deployed to demo.react-redux-firebase.com.
- Support for updating and nested props
- Population capability (similar to mongoose's
populate
or SQL'sJOIN
) - Out of the box support for authentication (with auto load user profile)
- Firebase Database, Firestore, Auth, Storage, and Messaging Support
- Support small data ( using
value
) or large datasets ( usingchild_added
,child_removed
,child_changed
) - queries including
orderByChild
,orderByKey
,orderByValue
,orderByPriority
,limitToLast
,limitToFirst
,startAt
,endAt
,equalTo
- Automatic binding/unbinding through
firestoreConnect
(manual throughwatchEvent
) - Declarative decorator syntax for React components
- Tons of integrations including
redux-thunk
andredux-observable
- Action Types and other Constants exported for external use (such as in
redux-observable
) - Firebase v3+ support
- Server Side Rendering Support
react-native
support using native modules or web sdk
npm install --save react-redux-firebase@next
Include reactReduxFirebase
in your store compose function and firebaseReducer
in your reducers:
import { createStore, combineReducers, compose } from 'redux'
import { reactReduxFirebase, firebaseReducer } from 'react-redux-firebase'
import firebase from 'firebase'
// import 'firebase/firestore' // <- needed if using firestore
const firebaseConfig = {}
// react-redux-firebase config
const rrfConfig = {
userProfile: 'users',
// useFirestoreForProfile: true // Firestore for Profile instead of Realtime DB
}
// initialize firebase instance
firebase.initializeApp(config) // <- new to v2.*.*
// initialize firestore
// firebase.firestore() // <- needed if using firestore
// Add reduxReduxFirebase enhancer when making store creator
const createStoreWithFirebase = compose(
reactReduxFirebase(firebase, rrfConfig), // firebase instance as first argument
// reduxFirestore(firebase) // <- needed if using firestore
)(createStore)
// Add Firebase to reducers
const rootReducer = combineReducers({
firebase: firebaseReducer,
// firestore: firestoreReducer // <- needed if using firestore
})
// Create store with reducers and initial state
const initialState = {}
const store = createStoreWithFirebase(rootReducer, initialState)
In components:
Add Data
import React from 'react'
import PropTypes from 'prop-types'
import { withFirebase } from 'react-redux-firebase'
const Todos = ({ firebase }) => {
const sampleTodo = { text: 'Sample', done: false }
const pushSample = () => firebase.push('todos', sampleTodo)
return (
<div>
<h1>Todos</h1>
<ul>
{todosList}
</ul>
<input type="text" ref="newTodo" />
<button onClick={pushSample}>
Add
</button>
</div>
)
}
export default withFirebase(Todos)
// or firebaseConnect()(Todos) if attaching listeners
Load Data (listeners managed on mount/unmount)
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { firebaseConnect, isLoaded, isEmpty } from 'react-redux-firebase'
const Todos = ({ todos, firebase }) => {
// 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={this.handleAdd}>
Add
</button>
</div>
)
}
export default compose(
firebaseConnect([
'todos' // { path: '/todos' } // object notation
]),
connect(
(state) => ({
todos: state.firebase.data.todos,
// profile: state.firebase.profile // load profile
})
)
)(Todos)
Queries Based On Props
It is common to make a detail page that loads a single item instead of a whole list of items. A query for a specific Todos
can be created using
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { firebaseConnect, getVal } from 'react-redux-firebase'
// Component enhancer that loads todo into redux then into the todo prop
const enhance = compose(
firebaseConnect((props) => [
// Set listeners based on props (prop is route parameter from react-router in this case)
return [
{ path: `todos/${props.params.todoId}` }, // create todo listener
// `todos/${props.params.todoId}` // equivalent string notation
]
}),
connect(({ firebase }, props) => ({
todo: getVal(firebase, `todos/${props.params.todoId}`), // lodash's get can also be used
}))
)
const Todo = ({ todo, firebase, params }) =>
<div>
<input
name="isDone"
type="checkbox"
checked={todo.isDone}
onChange={() =>
firebase.update(`todos/${params.todoId}`, { done: !todo.isDone })
}
/>
<span>{todo.label}</span>
</div>
// Export enhanced component
export default enhance(Todo)
Load Data On Click
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { withFirebase, isLoaded, isEmpty } from 'react-redux-firebase'
const Todos = ({ firebase }) => {
// 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>
<button onClick={() => firebase.watchEvent('value', 'todos')}>
Load Todos
</button>
</div>
)
}
// Export enhanced component
export default compose(
withFirebase, // or firebaseConnect()
connect((state) => ({
todos: state.firebase.data.todos,
// profile: state.firebase.profile // load profile
}))
)(Todos)
See full documentation at react-redux-firebase.com
Examples folder is broken into two categories complete and 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).
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.
Snippet showing how to use decorators to simplify connect functions (redux's connect
and react-redux-firebase's firebaseConnect
)
A simple example that was created using create-react-app's. Shows a list of todo items and allows you to add to them.
An example that user Material UI built on top of the output of create-react-app's eject command. Shows a list of todo items and allows you to add to them. This is what is deployed to redux-firebasev3.firebaseapp.com.
Join us on the redux-firebase gitter.
View docs for recipes on integrations with:
- redux-firestore
- redux-thunk
- redux-observable
- redux-saga
- redux-form
- redux-auth-wrapper
- redux-persist - improved integration with
v2.0.0
- react-native
- react-native-firebase - requires
v2.0.0
generator-react-firebase is a yeoman generator uses react-redux-firebase when opting to include redux.
The examples folder contains full applications that can be copied/adapted and used as a new project.
Please visit the FAQ section of the docs
This project exists thanks to all the people who contribute.
Thank you to all our backers! 🙏