mobx-firebase-store v1.2.1
mobx-firebase-store
MobxFirebaseStore allows you to subscribe to firebase data via firebase-nest subscriptions and have the data flow into mobx observable maps.
See live: storybook
React Component Example
import React, {Component} from 'react';
import MobxFirebaseStore from 'mobx-firebase-store';
import {observer} from 'mobx-react';
import {createAutoSubscriber} from 'firebase-nest';
import firebase from 'firebase';
const fbApp = firebase.initializeApp({
apiKey: 'yourApiKey',
authDomain: "localhost",
databaseURL: 'https://docs-examples.firebaseio.com',
storageBucket: 'docs-examples.firebaseio.com'
}, "chatApp");
const store = new MobxFirebaseStore(firebase.database(fbApp).ref());
/* Real-time messages */
class MessageList extends Component {
renderMessage(messageKey, messageData) {
return (
<div style={{border:'1px grey solid'}} key={messageKey}>
<div>{messageData.text}</div>
<div>Posted {new Date(messageData.timestamp).toString()}</div>
</div>
);
}
render() {
const messages = store.getData('myMsgs'); //'myMsgs' matches the subKey below
//autoSubscriber keeps track of loading and error status when using store.subscribeSubsWithPromise
const { _autoSubscriberFetching: fetching, _autoSubscriberError: fetchError, error } = this.state
//store.getData returns mobx observable map - use keys(), get(), entries(), etc. to render the data
//do NOT use set() or other mutations on the map -- updates should be written directly to firebase, and will get reflected in the observable map automatically.
if (!messages) {
return <div>Loading messages...</div>
}
return (
<div>
Messages:
{messages.keys().map(messageKey => this.renderMessage(messageKey, messages.get(messageKey)))}
</div>
);
}
}
//Subscribe to and observe firebase data
export default createAutoSubscriber({
getSubs: (props, state) => [{
subKey: 'myMsgs', //any unique string describing this subscription; must match getData call
asList: true, //or asValue: true. asList will internally subscribe via firebase child_added/removed/changed; asValue via onValue.
path: 'samplechat/messages', //firebase location,
//Optional - get data callbacks after store data is already updated:
onData: (type, snapshot) => console.log('got data: ', type, 'myMsgs', snapshot.val())
}], //can add more than one subscription to this array
subscribeSubs: (subs, props, state) => store.subscribeSubsWithPromise(subs)
})(observer(MessageList));react-native is supported - libs and usage are the same
Supports Firebase queries - filtering and sorting
export default createAutoSubscriber({
getSubs: (props, state) => [{
subKey: 'myMsgs',
asValue: true, //have to use asValue if using orderBy* and want to preserve the ordering in the observable map
resolveFirebaseRef: () => fbRef.child('samplechat/messages').orderByChild('sentTimestamp')
}],
subscribeSubs: (subs, props, state) => store.subscribeSubsWithPromise(subs)
})(observer(MessageList));Supports data transformation
With asValue sub, define transformValue : (val) => ... on the sub.
Or with asList, define transformChild: (val) => ....
Supports nested subscriptions
For example, for each message, subscribe to its author (message.uid).
//...
getSubs: (props, state) => [{
subKey: 'myMsgs',
asValue: true,
resolveFirebaseRef: () => fbRef.child('samplechat/messages'),
childSubs: (messageKey, messageData) => [{
subKey: 'user_' + messageData.uid,
asValue: true,
resolveFirebaseRef: () => fbRef.child('samplechat/users').child(messageData.uid)
}]
}],
//...If we have getSubs defined as above and 2 messages by 2 users, fred and barney, the subscription graph can be pictured something like this:

Also can nest subscriptions for specific fields - for example, parent subscription is for a blog, nested subscription is for its author.
getSubs: (props, state) => {
return [{
subKey: 'blog_'+props.blogKey,
asValue: true,
resolveFirebaseRef: () => fbRef.child('blogs').child(props.blogKey),
fieldSubs: {
authorKey: (authorKey) => [{subKey: 'user_' + authorKey, asValue: true, path: 'users/' + authorKey}]
}
}];
},See chat for examples of how to display the firebase subscription graph.
More examples
chat - includes auth
next.js example - server-side rendering with firebase-admin, firebase and mobx, and auth
react-native-gifted-chat example
Required libs
npm install mobx mobx-react firebase firebase-nest mobx-firebase-store --save
Run examples in storybook
Inspired by react-native-web-starter examples.
cd examples-storybookorcd examples-storybook-firebase3To run firebase3 examples, you need to set your API key in index.js. You can create one at https://console.cloud.google.com, credentials->create credentials->API key->browser key.
npm installnpm run storybook
Features
Firebase 3.x is supported (https://github.com/nyura123/mobx-firebase-store/tree/master/examples/listAndDetailFirebase3)
Allows to differentiate between data not being subscribed or loaded (
store.getData(...) === undefined) vs being empty.Writes to maps are done inside transactions for better performance.
Throttles writes by default - this helps if we want to avoid re-rendering too frequently, such as during initial load of data.
To turn off:
const store = new MobxFirebaseStore(fb, {throttle: {shouldThrottle: false}}).Throttling params can also be tweaked.
firebase-nestsubscriptions allow subscribing to whole graphs of data.For example, via a single subscription, subscribe to
itemsand to eachitems'scategory. If an item is ever deleted or its category is changed, the nested category subscription is deleted/changed automatically.store.subscribeSubsWithPromiseprovides a promise that resolves when initial data, including nested/child data, is loaded.MobxFirebaseStorecan be extended to optionally implement various callbacks:onData(type, snapshot, sub)-- be notified on every data update coming in from firebase after it has already been applied to observable maps.onWillSubscribe(sub),onWillUnsubscribe(subKey)
Exposes
subscribedRegistrywhich shows how many subscribers are currently listening to each piece of data.store.reset()can be used to unsubscribe from all data & reset the store (for example on user logout)Use
firebase-nestautoSubscriberto allow React components to specify their prop- and state-dependent subscriptions and be automatically subscribed/unsubscribed.If your component's props or state is updated, the subscriptions will be updated automatically.
firebase-nest&autoSubscriberboth minimize unnecessary ref.off()/ref.on() flickering.By default, data is removed from fbStore cache when it no longer has any subscribers.
When subscribing
asList,onDatawith type=FB_INIT_VALgets the whole initial list as one update.Firebase queries are supported via resolveFirebaseRef function you can set on each sub. Otherwise you can set path:
resolveFirebaseQuery: () => fbRef.child('yourPath')or
path: 'yourPath'
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago