Nefarious Pomegranate Magnate

    react-redux-firebase-interwebs

    1.1.6 • Public • Published

    react-redux-firebase

    Gitter

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

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

    Demo

    View deployed version of Material Example here

    Features

    • Integrated into redux
    • Support for updating and nested props
    • Population capability (similar to mongoose's populate or SQL's JOIN)
    • Out of the box support for authentication (with auto load user profile)
    • Firebase Storage Support
    • Support small data ( using value ) or large datasets ( using child_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
    • redux-thunk and redux-observable integrations
    • Action Types and other Constants exported for external use (such as in redux-observable)
    • Firebase v3+ support

    Install

    npm install --save react-redux-firebase

    Before Use

    Peer Dependencies

    Install peer dependencies: npm i --save redux react-redux

    Decorators

    Though they are optional, it is highly recommended that you used decorators with this library. The Simple Example shows implementation without decorators, while the Decorators Example shows the same application with decorators implemented.

    A side by side comparison using react-redux's connect function/HOC is the best way to illustrate the difference:

    class SomeComponent extends Component {
     
    }
    export default connect()(SomeComponent)

    vs.

    @connect()
    export default class SomeComponent extends Component {
     
    }

    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 by doing the following:

    1. run npm i --save-dev babel-plugin-transform-decorators-legacy
    2. Add the following line to your .babelrc:
    {
        "plugins": ["transform-decorators-legacy"]
    }
    

    Use

    Include reduxFirebase in your store compose function:

    import { createStore, combineReducers, compose } from 'redux'
    import { reactReduxFirebase, 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(
      reactReduxFirebase(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 { firebaseConnect, helpers } from 'react-redux-firebase'
    const { isLoaded, isEmpty, dataToJS } = helpers
     
    @firebaseConnect( [
      '/todos'
      // { type: 'once', path: '/todos' } // for loading once instead of binding
    ])
    @connect(
      ({ firebase }) => ({
        // Connect todos prop to firebase todos
        todos: dataToJS(firebase, '/todos'),
      })
    )
    export default 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>
        )
      }
    }

    Alternatively, if you choose not to use decorators:

     
    const wrappedTodos = firebaseConnect([
      '/todos'
    ])(Todos)
    export default connect(
      ({firebase}) => ({
        todos: dataToJS(firebase, '/todos'),
      })
    )(wrappedTodos)
     

    Documentation

    See react-redux-firebase.com

    Examples

    Examples folder is broken into two categories complete and snippets. Complete contains full applications that can be run as is, where as snippets is small amounts of code to show functionality (dev tools and deps not included).

    State Based Query Snippet

    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.

    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 the redux-firebase gitter.

    Using with redux-thunk

    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:

    createStore:

    import { applyMiddleware, compose, createStore } from 'redux';
    import thunk from 'redux-thunk';
    import { reactReduxFirebase, getFirebase } from 'react-redux-firebase';
    import makeRootReducer from './reducers';
     
    const fbConfig = {} // your firebase config
    const config = {
      userProfile: 'users',
      enableLogging: false
    }
    const store = createStore(
      makeRootReducer(),
      initialState,
      compose(
        applyMiddleware([
          thunk.withExtraArgument(getFirebase) // Pass getFirebase function as extra argument
        ]),
        reactReduxFirebase(fbConfig, )
      )
    );
     

    Action:

    const sendNotification = (payload) => {
      type: NOTIFICATION,
      payload
    }
    export const addTodo = (newTodo) =>
      (dispatch, getState, getFirebase) => {
        const firebase = getFirebase()
        firebase
          .push('todos', newTodo)
          .then(() => {
            dispatch(sendNotification('Todo Added'))
          })
      };
     

    Using with redux-observable

    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:

    import { getFirebase } from 'react-redux-firebase'
    import { combineEpics } from 'redux-observable'
     
    const rootEpic = (...args) =>
      combineEpics(somethingEpic, epic2)(..args, getFirebase)
     
    // then later in your epics
    const somethingEpic = (action$, store, getFirebase) =>
      action$.ofType(SOMETHING)
        .map(() =>
          getFirebase().push('somePath/onFirebase', { some: 'data' })
        )

    Generator

    generator-react-firebase uses react-redux-firebase when opting to include redux

    FAQ

    1. How is this different than redux-react-firebase?

    This library was actually originally forked from redux-react-firebase, but adds extended functionality such as:

    #### Well why not combine? I have been talking to the author of redux-react-firebase about combining, but we are not sure that the users of both want that at this point. Join us on the redux-firebase gitter if you haven't already since a ton of this type of discussion goes on there.

    Bottom line: The author of redux-react-firebase was absent when functionality was needed by me and others, so this library was created.

    1. Why use redux if I have Firebase to store state?

    This isn't a super quick answer, so I wrote up a medium article to explain

    Contributors

    Thanks

    Special thanks to Tiberiu Craciun for creating redux-react-firebase, which this project was originally based on.

    Install

    npm i react-redux-firebase-interwebs

    DownloadsWeekly Downloads

    3

    Version

    1.1.6

    License

    MIT

    Last publish

    Collaborators

    • interw3bs