Convert Figma logo to code with AI

prescottprue logoreact-redux-firebase

Redux bindings for Firebase. Includes React Hooks and Higher Order Components.

2,547
557
2,547
133

Top Related Projects

Hooks, Context Providers, and Components that make it easy to interact with Firebase.

The official, opinionated, batteries-included toolset for efficient Redux development

An alternative side effect model for Redux apps

8,477

The Redux Framework

27,618

Simple, scalable state management.

30,713

A reactive programming library for JavaScript

Quick Overview

React Redux Firebase is a higher-order component for integrating Firebase with React and Redux applications. It provides a set of Redux actions and reducers for Firebase services, making it easier to manage Firebase data in a Redux store and use it in React components.

Pros

  • Seamless integration of Firebase with React and Redux
  • Provides ready-to-use actions and reducers for common Firebase operations
  • Supports real-time data syncing and offline persistence
  • Offers hooks for easy access to Firebase data and authentication state

Cons

  • Learning curve for developers new to Redux or Firebase
  • Can add complexity to smaller projects that may not need Redux
  • Requires careful state management to avoid performance issues with large datasets
  • Limited customization options for some Firebase features

Code Examples

  1. Setting up the Firebase provider:
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { ReactReduxFirebaseProvider } from 'react-redux-firebase'
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
import { createStore, combineReducers } from 'redux'
import { firebaseReducer } from 'react-redux-firebase'

// Initialize Firebase
const fbConfig = {
  // your firebase config
}

firebase.initializeApp(fbConfig)

// Create store with reducers
const store = createStore(
  combineReducers({
    firebase: firebaseReducer
  })
)

const rrfProps = {
  firebase,
  config: {},
  dispatch: store.dispatch
}

render(
  <Provider store={store}>
    <ReactReduxFirebaseProvider {...rrfProps}>
      <App />
    </ReactReduxFirebaseProvider>
  </Provider>,
  document.getElementById('root')
)
  1. Using Firebase data in a component:
import React from 'react'
import { useFirebaseConnect, useFirestoreConnect } from 'react-redux-firebase'
import { useSelector } from 'react-redux'

function TodoList() {
  useFirebaseConnect([
    'todos'
  ])

  const todos = useSelector((state) => state.firebase.ordered.todos)

  return (
    <ul>
      {todos && todos.map((todo) => (
        <li key={todo.key}>{todo.value.text}</li>
      ))}
    </ul>
  )
}
  1. Performing a Firebase action:
import React from 'react'
import { useFirebase } from 'react-redux-firebase'

function AddTodo() {
  const firebase = useFirebase()

  const handleSubmit = (e) => {
    e.preventDefault()
    const todoText = e.target.elements.todoText.value
    firebase.push('todos', { text: todoText })
    e.target.reset()
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="todoText" />
      <button type="submit">Add Todo</button>
    </form>
  )
}

Getting Started

  1. Install the package:

    npm install react-redux-firebase
    
  2. Set up your Firebase config and initialize the app:

    import firebase from 'firebase/app'
    
    const fbConfig = {
      // Your Firebase config object
    }
    
    firebase.initializeApp(fbConfig)
    
  3. Add the Firebase reducer to your Redux store:

    import { firebaseReducer } from 'react-redux-firebase'
    import { combineReducers, createStore } from 'redux'
    
    const rootReducer = combineReducers({
      firebase: firebaseReducer,
      // ... other reducers
    })
    
    const store = createStore(rootReducer)
    
  4. Wrap your app with the ReactReduxFirebaseProvider:

    import { ReactReduxFirebaseProvider } from 'react-redux-firebase'
    
    const rrfProps = {
      firebase
    

Competitor Comparisons

Hooks, Context Providers, and Components that make it easy to interact with Firebase.

Pros of reactfire

  • Official Firebase SDK for React, ensuring better long-term support and compatibility
  • Simpler API with React hooks, making it easier to use Firebase services in functional components
  • Built-in support for Suspense, allowing for more efficient data loading and rendering

Cons of reactfire

  • Less integration with state management libraries like Redux
  • Fewer additional utilities and helper functions compared to react-redux-firebase
  • May require more manual setup for complex data structures and relationships

Code Comparison

react-redux-firebase:

import { useFirebase } from 'react-redux-firebase'

const MyComponent = () => {
  const firebase = useFirebase()
  const handleClick = () => firebase.push('todos', { text: 'New Todo' })
  return <button onClick={handleClick}>Add Todo</button>
}

reactfire:

import { useFirestore } from 'reactfire'

const MyComponent = () => {
  const firestore = useFirestore()
  const handleClick = () => firestore.collection('todos').add({ text: 'New Todo' })
  return <button onClick={handleClick}>Add Todo</button>
}

Both libraries provide ways to interact with Firebase services, but reactfire's API is more aligned with the official Firebase SDK and uses React hooks for a more modern approach. react-redux-firebase offers tighter integration with Redux and additional utilities, which may be beneficial for larger applications with complex state management needs.

The official, opinionated, batteries-included toolset for efficient Redux development

Pros of Redux Toolkit

  • Simplifies Redux setup with built-in utilities for common tasks
  • Includes RTK Query for efficient API calls and data fetching
  • Encourages best practices and reduces boilerplate code

Cons of Redux Toolkit

  • Steeper learning curve for developers new to Redux concepts
  • May be overkill for smaller applications with simple state management needs

Code Comparison

Redux Toolkit:

import { createSlice } from '@reduxjs/toolkit'

const counterSlice = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    increment: state => state + 1,
  },
})

React Redux Firebase:

import { firebaseReducer } from 'react-redux-firebase'

const rootReducer = combineReducers({
  firebase: firebaseReducer,
  // ... other reducers
})

Key Differences

  • Redux Toolkit focuses on general Redux state management, while React Redux Firebase specializes in Firebase integration
  • React Redux Firebase provides Firebase-specific actions and reducers out of the box
  • Redux Toolkit offers a more opinionated approach to Redux setup and configuration

Use Cases

  • Choose Redux Toolkit for general-purpose Redux applications with complex state management needs
  • Opt for React Redux Firebase when building Firebase-centric applications with React and Redux

Both libraries aim to simplify state management in React applications, but they cater to different specific needs and integration requirements.

An alternative side effect model for Redux apps

Pros of redux-saga

  • More powerful and flexible for complex asynchronous operations
  • Better testability due to generator functions
  • Extensive middleware ecosystem for advanced use cases

Cons of redux-saga

  • Steeper learning curve, especially for developers new to generators
  • More boilerplate code required for simple operations
  • Overkill for smaller applications with simpler state management needs

Code Comparison

redux-saga:

function* fetchUser(action) {
  try {
    const user = yield call(Api.fetchUser, action.payload.userId);
    yield put({type: "USER_FETCH_SUCCEEDED", user: user});
  } catch (e) {
    yield put({type: "USER_FETCH_FAILED", message: e.message});
  }
}

react-redux-firebase:

const mapStateToProps = (state) => ({
  profile: state.firebase.profile,
  auth: state.firebase.auth
});

export default compose(
  firebaseConnect(),
  connect(mapStateToProps)
)(MyComponent);

Summary

redux-saga is a more powerful and flexible solution for complex asynchronous operations, offering better testability and an extensive middleware ecosystem. However, it comes with a steeper learning curve and requires more boilerplate code. react-redux-firebase, on the other hand, provides a simpler integration with Firebase services and is more suitable for applications primarily using Firebase as their backend. The choice between the two depends on the specific needs of the project and the complexity of the state management requirements.

8,477

The Redux Framework

Pros of Rematch

  • Simpler API and less boilerplate code compared to traditional Redux
  • Built-in support for async actions without additional middleware
  • Encourages modular code organization with a plugin system

Cons of Rematch

  • Less mature ecosystem and community support
  • May require additional setup for integration with Firebase
  • Limited built-in functionality for real-time database operations

Code Comparison

React Redux Firebase:

import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/database'
import { createStore, combineReducers } from 'redux'
import { firebaseReducer } from 'react-redux-firebase'

const rootReducer = combineReducers({
  firebase: firebaseReducer
})

const store = createStore(rootReducer)

Rematch:

import { init } from '@rematch/core'
import * as models from './models'

const store = init({
  models,
})

React Redux Firebase provides a more integrated solution for Firebase and Redux, with built-in reducers and actions for common Firebase operations. It offers a comprehensive set of features specifically tailored for Firebase integration.

Rematch, on the other hand, focuses on simplifying Redux state management in general, without specific Firebase integration. It provides a more flexible and less opinionated approach to state management, which can be beneficial for projects that require custom solutions or don't heavily rely on Firebase.

The choice between these libraries depends on the project's specific needs, the level of Firebase integration required, and the developer's preference for API design and state management patterns.

27,618

Simple, scalable state management.

Pros of MobX

  • Simpler and more intuitive state management with less boilerplate code
  • Automatic tracking of state changes and re-rendering of components
  • Better performance for complex state updates due to fine-grained reactivity

Cons of MobX

  • Less predictable data flow compared to Redux's unidirectional approach
  • Steeper learning curve for developers familiar with Redux patterns
  • Potential for overuse of mutable state, which can lead to harder-to-debug issues

Code Comparison

react-redux-firebase:

import React from 'react'
import { useFirebase } from 'react-redux-firebase'

function AddTodo({ userId }) {
  const firebase = useFirebase()
  const addTodo = (title) => {
    firebase.push(`todos/${userId}`, { title, done: false })
  }
  // ... rest of component
}

MobX:

import React from 'react'
import { observer } from 'mobx-react-lite'
import { todoStore } from './stores'

const AddTodo = observer(({ userId }) => {
  const addTodo = (title) => {
    todoStore.addTodo(userId, title)
  }
  // ... rest of component
})

In this comparison, MobX offers a more straightforward approach to state management with less setup required. However, react-redux-firebase provides a more structured and predictable data flow, which can be beneficial for larger applications or teams with varying levels of experience.

30,713

A reactive programming library for JavaScript

Pros of RxJS

  • More versatile and can be used in various JavaScript environments, not limited to React and Redux
  • Provides powerful tools for handling complex asynchronous operations and event streams
  • Extensive ecosystem with a wide range of operators for data manipulation

Cons of RxJS

  • Steeper learning curve due to its functional reactive programming paradigm
  • May introduce unnecessary complexity for simpler Firebase-related tasks
  • Not specifically designed for Firebase integration, requiring additional setup

Code Comparison

RxJS:

import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';

fromEvent(input, 'input')
  .pipe(
    debounceTime(300),
    map(event => event.target.value)
  )
  .subscribe(value => console.log(value));

react-redux-firebase:

import { useFirebase } from 'react-redux-firebase'

const firebase = useFirebase()
firebase.push('todos', { text: 'Sample todo' })
  .then(() => {
    console.log('Todo added successfully')
  })

While RxJS offers powerful tools for handling complex asynchronous operations, react-redux-firebase provides a more straightforward approach for Firebase integration in React applications. RxJS excels in scenarios requiring advanced stream manipulation, while react-redux-firebase simplifies Firebase-related tasks within the React and Redux ecosystem.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

react-redux-firebase

NPM version NPM downloads Quality Code Coverage Code Style License Build Status

Gitter

Redux bindings for Firebase. Includes Higher Order Component (HOC) for use with React.

Usage Note

If you are starting a new project and/or are not required to have your Firebase data loaded into redux, you might want to give reactfire a try before trying react-redux-firebase. I wrote up a quick medium article explaining a bit about how, why, and showing how to start a new project with these tools.

Simple Example

Edit Simple Example

The Material Example is deployed to demo.react-redux-firebase.com.

Features

  • Out of the box support for authentication (with auto loading user profile from database/firestore)
  • Full Firebase Platform Support Including Real Time Database, Firestore, and Storage
  • Automatic binding/unbinding of listeners through React Hooks (useFirebaseConnect, useFirestoreConnect) or Higher Order Components (firebaseConnect and firestoreConnect)
  • Population capability (similar to mongoose's populate or SQL's JOIN)
  • 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 modules or web sdk

Installation

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.

Older Versions

Interested in support for versions of 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).

Use

Include 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/database'
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, useFirebase } from 'react-redux-firebase'
import { useParams } from 'react-router-dom'

export default function Todo() {
  const { todoId } = useParams() // matches todos/:todoId in route
  const firebase = useFirebase()

  useFirebaseConnect([
    { path: `todos/${todoId}` } // create todo listener
    // `todos/${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>
  )
}

export default function Todos() {
  const firebase = useFirebase()

  return (
    <div>
      <h1>Todos</h1>
      <EnhancedTodosList />
      <button onClick={() => firebase.watchEvent('value', 'todos')}>
        Load Todos
      </button>
    </div>
  )
}

Firestore

If you plan to use Firestore, you should checkout 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.

Docs

See full documentation at react-redux-firebase.com

Examples

Examples Folder

Examples folder is broken into two categories snippets and complete. /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).

State Based Query Snippet

Snippet showing querying based on data in redux state. One of the more common examples is querying based on the current users auth UID.

Decorators Snippet

Snippet showing how to use decorators to simplify connect functions (redux's connect and react-redux-firebase's firebaseConnect)

Simple App Example

A simple example that was created using create-react-app's. Shows a list of todo items and allows you to add to them.

Material App Example

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.

Discussion

Join us on the redux-firebase gitter.

Integrations

View docs for recipes on integrations with:

Starting A Project

Generator

generator-react-firebase is a yeoman generator uses react-redux-firebase when opting to include redux.

CRA Template

cra-template-rrf is a create-react-app template with react-redux-firebase included

Complete Examples

The examples folder contains full applications that can be copied/adapted and used as a new project.

FAQ

Please visit the FAQ section of the docs

Builds

Most commonly people consume Redux Firestore as a CommonJS module. This module is what you get when you import redux in a Webpack, Browserify, or a Node environment.

If you don't use a module bundler, it's also fine. The redux-firestore npm package includes precompiled production and development UMD builds in the dist folder. They can be used directly without a bundler and are thus compatible with many popular JavaScript module loaders and environments. For example, you can drop a UMD build as a <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.

Contributors

This project exists thanks to all the people who contribute.

NPM DownloadsLast 30 Days