Ditching setState for MobX

How to leverage observables, observers, computed properties, autorun & more to supercharge & simplify your React workflow.

In late 2017 I worked on a React Native project with a team that had used MobX as their state management library.

I had worked quite a bit with MobX in the past, but this team took it to another level, & I have to say not only did I like their approach but I learned quite a bit by working on the project & with the new team.

One of the big things that was different for me was that they had entirely done away with setState to manage local state and were instead using MobX not only to manage external state, but also local state.

They were not just using observables & observers, but were also using computed properties, autorun, & all that the framework has to offer.

This workflow brought a lot of power & benefit to the project, which we will outline in this post.

To use MobX in a React or React Native environment you must install a couple of dependencies: mobx, mobx-react, & babel-plugin-transform-decorators-legacy. You must also add the babel plugin to your .babelrc plugins configuration:
// .babelrc
{
// omitting pre-existing configuration
"plugins": [
"transform-decorators-legacy"
]

}

Getting Started

Let’s look at a really basic example of what I’m talking about and then go into some details about how we can also leverage things like computed values, autorun, & when.

This component will just toggle a Boolean to show & hide some UI:

  1. Import both observable & observer from mobx & mobx-react.
  2. Decorate the class as an observer.
  3. Create an observable value (this.boxVisible).
  4. We update the boxVisible value & the component re-renders (goodbye setState)!

If you’re not familiar with how MobX React works, the framework tracks which observables are used by render and automatically re-renders the component when one of these values changes.

This means you can just change any value that you are using in you UI and update the values, re-rendering your component without having to call setState!

Demo:

Computed Properties

Well what can I say about computed properties? They’re amazing and one of the reasons why working with MobX is so much fun! Moving them into the component makes React just that much more fun as well.

Computed properties are values that can be derived from the existing state or other computed values. Computed values are automatically derived from your state if any value that affects them changes.

@observable todos = [];
@computed get unfinishedTodoCount() {
return this.todos.filter(todo => !todo.finished).length;
}
// somewhere in render
<p>Unfinished todos: { this.unfinishedTodoCount }</p>

If todos ever changes, the new computed value will automatically be calculated and updated in our UI without us having to do any work.

Usage in a React class:

  1. We create two observable values, price & tax.
  2. The @computed total method returns a calculated value based on the price & tax.
  3. We use the computed value in our render method.
See demo here.

When

When will watch for a declaration to return true, and when it returns true it will run a function.

when(predicate: () => boolean, effect?: () => void, options?)

You could think of it as a reactive if this then that that & will watch when the predicate returns true to then run a given function.

From the docs: observes & runs the given predicate until it returns true. Once that happens, the given effectis executed and the autorunner is disposed. The function returns a disposer to cancel the autorunner prematurely.

Let’s look at an example that may work good in a game. For example, you want to show some type of message or do some sort of thing once a value gets to a certain number. In our example, we’ll wait for the score to reach 5 and when it does we’ll show a message to the user:

Usage in a React class:

  1. We create two observable values, score & showWin.
  2. We create a when function in the class.
  3. When score reaches 5, the second function is fired and the showWin Boolean is set to true

Autorun

autorun is a way to call function when a computed value has changed.

From the docs: can be used in those cases where you want to create a reactive function that will never have observers itself. This is usually the case when you need to bridge from reactive to imperative code, for example for logging, persistence, or UI-updating code. When autorun is used, the provided function will always be triggered once immediately and then again each time one of its dependencies changes.

Usage in a React class:

In this example, whenever the name property of the class changes, the autorun function will be called.

  1. Import autorun from MobX.
  2. Create an autorun function that will run whenever the name value is changed, logging out a message with the new name
See demo here.

Benefits

Michel Weststrate, the author of MobX, wrote an article outlining why he has also adopted this technique. This article articulated why you would replace setState with MobX with a few good reasons & explanation around those reasons.

  1. MobX is synchronous while setState is asynchronous
  2. setState causes unnecessary renders
  3. setState is not sufficient to capture all component state

I won’t repeat his points, but if you’re interested to read more check out his article 3 Reasons Why I Stopped Using setState.

More powerful

In addition to replacing setState, you are also getting all of the functionality that MobX has to offer and adding it to your React workflow directly in your React classes.

Conclusion

Reactive programming is extremely powerful and fun, but a lot of the current entry points such as RxJS are notoriously hard to get into for programmers new to the paradigm.

MobX offers not only an extremely intuitive entry and approach to Reactive programming but also what is in my opinion the best approach currently available for React developers, and with mobx-react it is a dream come true for React developers.

I truly think that by adopting this technique you may never need to use setState again by combining the best of what both React & MobX have to offer.

To learn more about not only MobX, but all of the state management techniques available right now in the React ecosystem check out this article by Gant Laborde.

My Name is Nader Dabit . I am a Developer Advocate at AWS Mobile working with projects like AppSync and AWS Amplify, and the founder of React Native Training.
If you enjoyed this article, please clap n number of times and share it! Thanks for your time.