npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mobx-firebase-store

v1.2.1

Published

mobx store with dynamic firebase subscriptions and data

Downloads

86

Readme

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:

subscription graph

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

firebase queries - pagination

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.

  1. cd examples-storybook or cd examples-storybook-firebase3

To 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.

  1. npm install

  2. npm run storybook

Features

  1. Firebase 3.x is supported (https://github.com/nyura123/mobx-firebase-store/tree/master/examples/listAndDetailFirebase3)

  2. Allows to differentiate between data not being subscribed or loaded (store.getData(...) === undefined) vs being empty.

  3. Writes to maps are done inside transactions for better performance.

  4. 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.

  5. firebase-nest subscriptions allow subscribing to whole graphs of data.

    For example, via a single subscription, subscribe to items and to each items's category. If an item is ever deleted or its category is changed, the nested category subscription is deleted/changed automatically.

  6. store.subscribeSubsWithPromise provides a promise that resolves when initial data, including nested/child data, is loaded.

  7. MobxFirebaseStore can 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)
  8. Exposes subscribedRegistry which shows how many subscribers are currently listening to each piece of data.

  9. store.reset() can be used to unsubscribe from all data & reset the store (for example on user logout)

  10. Use firebase-nest autoSubscriber to 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.

  11. firebase-nest & autoSubscriber both minimize unnecessary ref.off()/ref.on() flickering.

  12. By default, data is removed from fbStore cache when it no longer has any subscribers.

  13. When subscribing asList, onData with type=FB_INIT_VAL gets the whole initial list as one update.

  14. 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'