This wants to be a very simple and quick guide to using Mobx togheter with React Native for people with a minimum of experience on concept like React, RxJS, Observables, Flux, etc.
Prepare React Native
First step is to add mobx to your react native installation by installing npm packages:
react-native install mobx react-native install mobx-react react-native install babel-preset-react-native react-native install babel-plugin-transform-decorators-legacy
and make sure that .babelrc contains at least those lines:
{ "presets": ["react-native"], "plugins": ["transform-decorators-legacy"] }
Then relaunch your app on the phone.
Creating the observables within the Store
To make things simpler we’ll add just a single store to our app.
Create a new class in a javascript file called TestStore.js similar to the example below and decorate with @observable any variables you wish that your App will listen onto. Also decorate with @action the methods that will modify those variables.
import {observable, action} from 'mobx' class TestStore { @observable loading = true; @action loadingCompleted() { this.loading = false; } @action toggleLoading() { this.loading = this.loading ? false : true; } } export default new TestStore();
Passing the Store to every Component
To inject our store’s instance in every component that requires it then we need to decorate our App’s main component with the mobx’s Provider component as in the example:
import { Provider } from 'mobx-react'; import TestStore from './providers/TestStore'; export default class App extends React.Component { render() { return ( <Provider store={TestStore}> <TopStackNavigation/> </Provider> ); } }
TopStackNavigator is a complex Componenent based on the navigator from reactnavigation.org.
Once its wrapped by the Provider component then our TestStore’s instance will be available in every child component that require it.
Using the Store inside the Component
Its time to see everything in action. To use the store from a child component then you have to use two mobx’s decorators: inject and observer. See the example:
import {inject, observer} from "mobx-react/native"; @inject('store') @observer export default class LandingPage extends React.Component { componentDidMount() { setTimeout(() => { this.props.store.loadingCompleted(); }, 1000); } render() { return ( <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <ActivityIndicator color="#0000ff" animating={this.props.store.loading} size="large" /> <Text>Landing Page</Text> </View> ); } }
So, what this code will do is to display a rotating ActivityIndicator component because loading starting value is TRUE.
After 1 second our timeout will trigger and it will call the store’s action loadingCompleted() that will set loading to FALSE.
MOB’x will trigger the render() of this component because it uses this.props.store.loading and the indicator will stop rotating and disappear.
From my evidence (need some more testing or reading the internal docs), it seems taht if you remove this.props.store.loading from the component it will not trigger because MOBX will responde only to observable that you’re really listening and not the whole store that has been injected.
Triggering Action when something Happen
Ok so mobx will render our page magically if something happen. But what about switching page? I wish to change page when loading is completed.
This can be done in a couple of ways with mobx since it provides more API to manage those observables.
The most simple and usefull is when(). Lets change our component to swith page when loading is completed:
componentDidMount() { when('loading-debug', () => !this.props.store.loading, () => { console.info('Loading is true!'); this.props.navigation.dispatch(setRootMainPage); }); /*... omissis...*/ }
Remember to import “when” from the mobx library.
This function (click here for the docs) will monitor the function passed as 2nd argument and “when” it becomes TRUE then it will execute the function passed as 3th argument.
It automatically dispose of itself when triggered so its only fires one time. Its a good idea to dispose of it in componentWillUnmount().
In our example will load the real App’s homepage when loading is finished.