visit
I recently started to build several projects in React and React Native. The first one is a fitness app. The second on is a set of . With the third one, currently in progress, I’m trying to use the latest novelties in the space. Novelties such as the . So when Firebase announced its latest baby, Cloud Firestore, I started to migrate my code to the new product. While doing so, I noticed a redundancy when doing the data binding between MobX and Firebase as well as an opportunity to factor it.
If you use Firestore with React and MobX, a big chunk of your code is likely following the pattern below.@observerclass MyComponent extends Component<MyComponentProps, {}> { render() { const {loading, data} = this.store; if (loading) { return <LoadingIndicator />; } else if (!data) { return <NotFound />; } else { return <DisplayData {...{data}} />; } }}
When the user load a screen, you request the necessary data from Firebase. While waiting for the answer, you are likely to display a loading indicator of some kind. The data might not be found or an error might happen. In that case, you need to display a status message to the user, typically a “not found” or error screen. If the data is successfully delivered, you can finally display the component. This means that there can be a lot of redundant code for every screen of your app. The code snippet below is a typical example of how this flow looks like.
@observable loading = true;@observable data: Data;async componentWillMount() { try { const snapshot = await fb.doc(`collection/doc`).get(); if (snapshot.exists) { this.data = snapshot.data(); } } catch(e) { // There can be some extra error processing } this.loading = false;}
However this logic we just described can be captured by the following interface:
interface FireDocument<T> { loading(): boolean; exists(): boolean; get(): T;}
And below is an example of this interface in action.
@observerclass MyComponent extends Component<MyComponentProps, {}> { store: FireDocument<Data>; componentWillMount() { this.store = new FireDocument(fb.doc(`collection/doc`)); } render() { const {store} = this; if (store.loading()) { return <LoadingIndicator />; } else if (!store.exists()) { return <NotFound />; } else { return <DisplayData {...{data}} />; } }}
Pretty slick right? I published an implementation of FireDocument
and FireCollection
. Please let me know if this is useful to you and if you would like me to publish this as a proper NPM package.
The FireCollection
is almost identical to FireDocument
. It takes a query snapshot as argument.
const query = firebase.db.collection(`collection`) .where("prop", "==", "value");this.store = New FireCollection(query);
When dealing with collections, there are a couple some minor things to consider. You might want to filter some of the items on the client side and transform the result to another representation.
this.store = New FireCollection(query);this.store.setFilter(doc => doc.data().prop === true);this.store.setTransform(docs => ({ docs: docs.map(doc => doc.data())}));
Do you find this wrapper useful? Should I publish it as proper package? What are the other possible ways to integrate Firestore and MobX together?
const config = { Loading: <LoadingIndicator />, notFound: <PageNotFound />, resolve: (routerParams) => `users/${routerParams.uid}`};@bindDocument<User>(config)class User extends Component<UserProps, {}> { render() { const {user} = this.store; return <div>Hello ${user.name}</div>; }}
Could a decorator like this one be useful? I’m looking forward to read your thoughts on this topic.
Looking for a premium React Native starter kit that integrates with Cloud Firestore? Checkout the story below.
Live Coding — Integrating Firebase in React Native_I recently built a new version of the React Native Fiber starter kit that integrates with Firebase. You can check it…_gzht888.com