A simple introduction to state management with MobX in React Native
setState(..)
is the most fundamental call in any RN Component. Often, you notice a pattern where child component’s state is derived from props received from parent component. This quickly becomes unmanageable once your application starts growing. Thats exactly solutions like Redux and MobX solve. There are bunch of articles and resources explaining the difference between these two fantastic solutions and their approach to solving state management.
If you have been a native developer on Android/iOS exploring RN, you sure are bound to know good deal of Object Oriented ways. This is where MobX shines, it has tremendous OO appeal. In this article we will explore the core concepts of MobX via a simple RN application.
Note: For in depth understanding you can follow this article and for a bit more involved RN example you can follow this one and this one. Also excellent documentation in MobX home page.
Here is a simple break down of main concepts
Stores
form your data sources. A store is basically a simple ES6 class. Eventually state is derived from data sources automagically by MobX through ES6 decorators.- Store exposes
observable
fields, to which anobserver
reacts. - Store additionally can expose derived
observable
fields as well. They are pure functions onobservable
fields. MobX calls themcomputed
fields. - Store can change values of
observable
fields viaactions
. This is the only way MobX allows you to change state.
Lets explore a simple CounterStore. It provides an observable field called count and actions increment
and decrement
to alter the value.
// @flowimport { observable, action } from "mobx";export default class CounterStore { @observable count = 0; @action increment() {
this.count += 1;
}
@action decrement() {
this.count -= 1;
}}
Here is a look at a component that observes count and re-renders every time count value is changed.
// RN imports
import { observer, inject } from "mobx-react";@inject("counterStore")
@observer
class Counter extends Component {
render() {
return <Text>Count: {this.props.counterStore.count}</Text>;
}
}
By simply decorating class with @observer
MobX infers reactions to store changes, auto magically subscribes to them and re renders the component on changes. @inject
is MobX decorator that will provide component props with the mentioned store.
MobX provides a React Provider that can be setup as a parent component to all the components of your application. A MobX provider should be initialised with all the stores that you would want to be injected into your components.
import { Provider } from "mobx-react";export default class App extends Component {
render() {
return (
<Provider {counterStore: new CounterStore(), userStore: new UserStore()}>
<Home />
</Provider>
);
}
}
Now all the children of Home
component can be injected with counterStore
and userStore
.
Lets take a look at another example. A User Store that has observable fields for firstName, lastName, email, phone and fullName.
/* @flow */import { observable, action, computed } from "mobx";
export default class UserStore {
@observable firstName = "Sen";
@observable lastName = "Appleseed";
@observable email = "send@appleseed.com";
@observable phone = "1155667788";
@action data(data: Object) {
if (data.firstName) {
this.firstName = data.firstName;
}
if (data.lastName) {
this.lastName = data.lastName;
}
if (data.email) {
this.email = data.email;
}
if (data.phone) {
this.phone = data.phone;
}
}
@computed get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}}
An interesting function is the fullName
function. It is basically computed out of firstName and lastName observable fields.
MobX strongly encourages to keep the state information as minimal as possible and derive other state information with @computed
get decorators that are pure functions of other observable fields.
@inject("userStore")
@observer
class FullName extends Component {
render() {
return <Text>FullName: {this.props.userStore.fullName}</Text>;
}
}
Whenever value for firstName or lastName changes fullName component is automatically re-rendered.
Thats it, utilising ES Next decorators, MobX auto magically handles subscriptions to observable fields and re renders required components. Plus the code looks so much better and readable.
Checkout the entire project on GitHub