| Jun | JUL | Aug |
| 20 | ||
| 2019 | 2020 | 2021 |
COLLECTED BY
Collection: Alexa Crawls
useFirebaseConnect, useFirestoreConnect) or Higher Order Components (firebaseConnect and firestoreConnect)
●Population capability (similar to mongoose'spopulate or SQL'sJOIN)
●Support small data ( using value ) or large datasets ( using child_added, child_removed, child_changed )
●Multiple queries types supported including orderByChild, orderByKey, orderByValue, orderByPriority, limitToLast, limitToFirst, startAt, endAt, equalTo
●Tons of examples of integrations including redux-thunk and redux-observable
●Server Side Rendering Support
●react-native support using native modulesorweb sdk
npm install --save react-redux-firebase
This assumes you are using npm as your package manager.
If you're not, you can access the library on unpkg, download it, or point your package manager to it. Theres more on this in the Builds section below.
react-redux before v6 or the new react context API? Checkout the v2.*.* versions (installed through npm i --save react-redux-firebase^@2.5.0).
firebaseReducer (reducer) while creating your redux store then pass dispatch and your firebase instance to ReactReduxFirebaseProvider (context provider):
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import firebase from 'firebase/app'
import 'firebase/auth'
// import 'firebase/firestore' // <- needed if using firestore
// import 'firebase/functions' // <- needed if using httpsCallable
import { createStore, combineReducers, compose } from 'redux'
import {
ReactReduxFirebaseProvider,
firebaseReducer
} from 'react-redux-firebase'
// import { createFirestoreInstance, firestoreReducer } from 'redux-firestore' // <- needed if using firestore
const fbConfig = {}
// react-redux-firebase config
const rrfConfig = {
userProfile: 'users'
// useFirestoreForProfile: true // Firestore for Profile instead of Realtime DB
}
// Initialize firebase instance
firebase.initializeApp(fbConfig)
// Initialize other services on firebase instance
// firebase.firestore() // <- needed if using firestore
// firebase.functions() // <- needed if using httpsCallable
// 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 = createStore(rootReducer, initialState)
const rrfProps = {
firebase,
config: rrfConfig,
dispatch: store.dispatch
// createFirestoreInstance // <- needed if using firestore
}
// Setup react-redux so that connect HOC can be used
function App() {
return (
<Provider store={store}>
<ReactReduxFirebaseProvider {...rrfProps}>
<Todos />
</ReactReduxFirebaseProvider>
</Provider>
)
}
render(<App />, document.getElementById('root'))
The Firebase instance can then be grabbed from context within your components (withFirebase and firebaseConnect Higher Order Components provided to help):
Add Data
import React from 'react'
import { useFirebase } from 'react-redux-firebase'
export default function Todos() {
const firebase = useFirebase()
function addSampleTodo() {
const sampleTodo = { text: 'Sample', done: false }
return firebase.push('todos', sampleTodo)
}
return (
<div>
<h1>New Sample Todo</h1>
<button onClick={addSampleTodo}>Add</button>
</div>
)
}
Load Data (listeners automatically managed on mount/unmount)
import React from 'react'
import PropTypes from 'prop-types'
import { useSelector } from 'react-redux'
import { useFirebaseConnect, isLoaded, isEmpty } from 'react-redux-firebase'
export default function Todos() {
useFirebaseConnect([
'todos' // { path: '/todos' } // object notation
])
const todos = useSelector((state) => state.firebase.ordered.todos)
if (!isLoaded(todos)) {
return <div>Loading...</div>
}
if (isEmpty(todos)) {
return <div>Todos List Is Empty</div>
}
return (
<div>
<ul>
{Object.keys(todos).map((key,id) => (
<TodoItem key={key} id={id} todo={todos[key]} />
))}
</ul>
</div>
)
}
Queries Based On Route Params
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 { get } from 'lodash'
import { useSelector } from 'react-redux'
import { useFirebaseConnect } from 'react-redux-firebase'
import { useParams } from 'react-router-dom'
export default function Todo() {
const { todoId } = useParams() // matches todos/:todoId in route
useFirebaseConnect([
{ path: `todos/${todoId}` } // create todo listener
// `todos/${props.params.todoId}` // equivalent string notation
])
const todo = useSelector(
({ firebase: { data } }) => data.todos && data.todos[todoId]
)
function updateTodo() {
return firebase.update(`todos/${params.todoId}`, { done: !todo.isDone })
}
return (
<div>
<input
name="isDone"
type="checkbox"
checked={todo.isDone}
onChange={updateTodo}
/>
<span>{todo.label}</span>
</div>
)
}
Load Data On Click
import React from 'react'
import { useSelector } from 'react-redux'
import { useFirebase, isLoaded, isEmpty } from 'react-redux-firebase'
function TodosList() {
const todos = useSelector((state) => state.firebase.ordered.todos)
if (!isLoaded(todos)) {
return <div>Loading...</div>
}
if (isEmpty(todos)) {
return <div>Todos List Is Empty</div>
}
return (
<ul>
{Object.keys(todos).map((key,id) => (
<TodoItem key={key} id={id} todo={todos[key]} />
))}
</ul>
)
}
function Todos() {
const firebase = useFirebase()
return (
<div>
<h1>Todos</h1>
<EnhancedTodosList />
<button onClick={() => firebase.watchEvent('value', 'todos')}>
Load Todos
</button>
</div>
)
}
// Export enhanced component
export default Todos
redux-firestore. It integrates nicely with react-redux-firebase and it allows you to run Real Time Database and Firestore along side each other.
react-redux-firebase provides the firestoreConnect HOC (similar to firebaseConnect) for easy setting/unsetting of listeners.
Currently react-redux-firebase still handles auth when using 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.
/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).
connect and react-redux-firebase'sfirebaseConnect)
<script> tag on the page. The UMD builds make Redux Firestore available as a window.ReactReduxFirebase global variable.
It can be imported like so:
<script src="../node_modules/react-redux-firebase/dist/react-redux-firebase.min.js"></script>
<script src="../node_modules/redux-firestore/dist/redux-firestore.min.js"></script>
<!-- or through cdn: <script src="https://unpkg.com/react-redux-firebase@latest/dist/react-redux-firebase.min.js"></script> -->
<!-- or through cdn: <script src="https://unpkg.com/redux-firestore@latest/dist/redux-firestore.min.js"></script> -->
<script>
console.log('react redux firebase:', window.ReactReduxFirebase)
</script>
Note: In an effort to keep things simple, the wording from this explanation was modeled after the installation section of the Redux Docs.