import { createStore, combineReducers, compose } from 'redux';
import { reduxFirestore, firestoreReducer } from 'redux-firestore';
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/database';
import 'firebase/firestore';
const firebaseConfig = {}; // from Firebase Console
const rfConfig = {}; // optional redux-firestore Config Options
// Initialize firebase instance
firebase.initializeApp(firebaseConfig);
// Initialize Cloud Firestore through Firebase
firebase.firestore();
// Add reduxFirestore store enhancer to store creator
const createStoreWithFirebase = compose(
reduxFirestore(firebase, rfConfig), // firebase instance as first argument, rfConfig as optional second
)(createStore);
// Add Firebase to reducers
const rootReducer = combineReducers({
firestore: firestoreReducer,
});
// Create store with reducers and initial state
const initialState = {};
const store = createStoreWithFirebase(rootReducer, initialState);Then pass store to your component's context using react-redux's Provider:
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
render(
<Provider store={store}>
<MyRootComponent />
</Provider>,
rootEl,
);Enable browser debugging to troubleshoot dataflow issues
localStore.debug='rrf:*'
localStore.debug='rrf:cache'
localStore.debug='rrf:mutate'
localStore.debug='rrfVerbose:*'It is common to make react components "functional" meaning that the component is just a function instead of being a class which extends React.Component. This can be useful, but can limit usage of lifecycle hooks and other features of Component Classes. recompose helps solve this by providing Higher Order Component functions such as withContext, lifecycle, and withHandlers.
import { connect } from 'react-redux';
import {
compose,
withHandlers,
lifecycle,
withContext,
getContext,
} from 'recompose';
const withStore = compose(
withContext({ store: PropTypes.object }, () => {}),
getContext({ store: PropTypes.object }),
);
const enhance = compose(
withStore,
withHandlers({
loadData: (props) => () => props.store.firestore.get('todos'),
onDoneClick: (props) => (key, done = false) =>
props.store.firestore.update(`todos/${key}`, { done }),
onNewSubmit: (props) => (newTodo) =>
props.store.firestore.add('todos', { ...newTodo, owner: 'Anonymous' }),
}),
lifecycle({
componentDidMount(props) {
props.loadData();
},
}),
connect(({ firebase }) => ({
// state.firebase
todos: firebase.ordered.todos,
})),
);
export default enhance(SomeComponent);For more information on using recompose visit the docs
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { watchEvents, unWatchEvents } from './actions/query';
import { getEventsFromInput, createCallable } from './utils';
class Todos extends Component {
static contextTypes = {
store: PropTypes.object.isRequired,
};
componentDidMount() {
const { firestore } = this.context.store;
firestore.get('todos');
}
render() {
return (
<div>
{todos.map((todo) => (
<div key={todo.id}>{JSON.stringify(todo)}</div>
))}
</div>
);
}
}
export default connect((state) => ({
todos: state.firestore.cache.todos.docs,
}))(Todos);