# :fire: :hatching_chick: {%= name %} {%= badge("fury") %} {%= badge("travis") %} [![Firebase](https://raw.githubusercontent.com/firebase/firebase-chrome-extension/master/icons/icon48.png)](https://www.firebase.com) [![ReactJS](https://raw.githubusercontent.com/facebook/react/master/docs/img/logo_small.png)](https://facebook.github.io/react) > {%= description %} {%= badge("npm") %} Firedux (*fiery·ducks*) wraps the [Firebase][firebase] [JavaScript API](https://www.firebase.com/docs/web/api/) to dispatch [Redux] actions that optimisically & immediately read/write to an in-memory subset of your data from Firebase, then asynchronously pull & push data in the background. Also supports some authentication methods and actions. Works well with [React]. Support firedux and fiery ducks like Magmar! ![Magmar](docs/magmar.gif) {%/* ## Table of contents */%} ## Install {%= include("install-npm", { save: true }) %} You'll need to configure `redux-thunk` on your Redux store. ## Use See [my TodoMVC example](https://github.com/AndersDJohnson/firedux-todomvc), the [tests](test/index.js), and below: ```js import Firedux from 'firedux' import Firebase from 'firebase' import { createStore, applyMiddleware, combineReducers } from 'redux' import thunk from 'redux-thunk' /** * For Firebase 2.x, e.g.: */ var ref = new Firebase('https://redux-firebase.firebaseio.com/') /** * Or for Firebase 3.x, e.g.: */ var app = Firebase.initializeApp({ apiKey: '', authDomain: '', databaseURL: 'https://redux-firebase.firebaseio.com/', storageBucket: '' }) var ref = app.database().ref() /** * Then create your Firedux instance, passing it your database reference as `ref`. */ const firedux = new Firedux({ ref, // Optional: omit: ['$localState'] // Properties to reserve for local use and not sync with Firebase. }) const reducer = combineReducers({ firedux: firedux.reducer() // Your other reducers... }) // Create store with middleware, including thunk. const store = applyMiddleware( thunk // Your other middleware... )(createStore)(reducer) // Set dispatch function from store on your Firedux instance. firedux.dispatch = store.dispatch // Later, you can subscribe to state. store.subscribe(() => { const state = store.getState() const { data, authData } = state.firedux console.log('Test data from Firebase:', data.test) // Lazy loading // e.g. once authorized, get user data: if (authData && authData.auth && authData.auth.uid) { firedux.watch(`users/${authData.auth.uid}`) } }) // Watch a path: firedux.watch('users/joe') .then(({snapshot}) => {}) // state.firedux.data.users.joe // Note: this promise will only resolve on the first value, // but it'll keep syncing on all value updates. // Get: firedux.get('posts/123') .then(({snapshot}) => {}) // state.firedux.data.posts['123'] // Set: firedux.set('test', true) .then(({value}) => {}) // state.firedux.data.test == true // Update (merging set): firedux.update('users/joe', { job: 'developer' }) .then(({value}) => {}) // state.firedux.data.users.joe == { name: 'Joe', job: 'developer' } // Push (to a collection): firedux.push('users', { name: 'Jane' }, (id) => { // The ID is generated locally immediately, // so you can get it before the push with this callback. // id == '-K95Cjx-caw2uSNsFJiI' }) .then((id) => {}) // state.firedux.data.users['-K95Cjx-caw2uSNsFJiI'] == { name: 'Jane' } // Remove: firedux.remove('users/joe') .then(() => {}) // state.firedux.data.users['joe'] == undefined // Auth // WARNING: Auth methods may only support Firebase 2.x for now. // Init // Call this when your app starts, to get existing session, and listen for auth changes. firedux.init() // See Login state below. // Login firedux.login({ email: 'user@example.com', password: '123' }) // state.firedux.authData == { auth: { uid: '123' } } // etc. `authData` per https://www.firebase.com/docs/web/api/firebase/authwithcustomtoken.html // or state.firedux.authError == Error // Logout firedux.logout() // state.firedux.authData == null // To handle some unsupported features, you can get access to the underlying Firebase instance via: firedux.ref // e.g. turn off a watch: firedux.ref.child('users/joe').off('value') // or login with OAuth: firedux.ref.authWithOAuthPopup("twitter", (error, authData) => { store.dispatch({type: 'FIREBASE_LOGIN', error, authData}) }) ``` ## Analytics This component includes tracking via Google Analytics. The purpose is to better understand how and where it's used, as a guide for development. To opt-out of this tracking, before loading the script on your page, use the global options in JavaScript, with `noTrack` set to `true`, as follows: ```js window.FIREDUX_OPTIONS = { noTrack: true }; ``` ## Running tests {%= include("tests") %} ## Contributing {%= include("contributing") %} {%= include("contributing-extra") %} ## Author {%= include("author") %} ## License {%= copyright({start: 2015, linkify: true}) %} {%= license({linkify: true}) %} *** {%= include("footer") %} [react]: https://facebook.github.io/react/ [redux]: http://redux.js.org/ [firebase]: https://www.firebase.com/