DEV Community

Ryan Dsouza
Ryan Dsouza

Posted on • Updated on

Using MobX with React Hooks

This post assumes familiarity with MobX.

Hooks have drastically changed the way we can write functional components in React.

This proposal has brought a huge change in a way we would write functional components. Combining this with a state management lib like MobX, it is too easy to manage you app state and never write a class component ever again.

For React, we get official bindings via the mobx-react package. But for hooks, we need to use another library mobx-react-lite. This gives us custom hooks with which we can create observables directly in our components.

A simple example is shown below:

Here, the hook useObservable gives us a new way of creating observables, actions and computed properties all in one object. The required values can be accessed on this object and the component reacts to changes via the observer wrapper.

Now you might be wondering, what if I have state that needs to be shared across components? mobx-react-lite doesn't include a Provider but we don't need it anymore as React already has that pattern... Context!

Context is the way we can share state across multiple components without techniques like lifting state up or prop-drilling. React now provides a hook called useContext that can help us share our MobX store across multiple components.

Here is the same example featuring the classic MobX store defined as a class and being used via context.

If you view the TodoStore.js file, you can see that it is how you would normally define a MobX store. A context is created out of an instance of this store and this now can be shared across multiple components. Easy!

I will write a follow-up post on how to test these components. Thanks for reading!

Top comments (9)

englund0110 profile image
Søren Englund • Edited

I actually also have a question. How would you be able to call a store, from anywhere else than a hook? Lets say that i have a http class that has a post method that makes a request, and then receives a error back. From my http class i want to call my ToasterStore with that error message, and then the ToasterComponent should update. Is that even possible to do?

ryands17 profile image
Ryan Dsouza

I think a better option would be that instead of calling the ToasterStore from your http class, you should call your ToasterStore from the store that you are calling your http class method in. Let's call that the DataStore

In MobX, you can combine the DataStore with your ToasterStore by creating a RootStore as described in this article

After that, call you error message method from the ToasterStore in your DataStore, this will maintain separation of concerns as the http class only now has to worry about fetching data and not update the UI.

grizllym profile image
Michal Griessel • Edited

I have question.

TodoStore.js could create new Todos object and exports it. And index.js could simply import that store and use it (I test it and it works).

Is there any reason why use useContext if it works without it?

ryands17 profile image
Ryan Dsouza

Good question! If you're just going to deploy your React app as a static website i.e. client-side rendering, you can directly import the store instance it wouldn't make any difference, but for server-side rendering, passing the store via context is essential. I will also be making an example on server-side rendering with MobX

rthomson3 profile image

Great article showing how to use hooks with a classic mobx store.
For the case where the class store has a constructor with parameters say new Todos(param1, param2), how would those be passed using createContext in your example without breaking reactivity?

englund0110 profile image
Søren Englund

Great examples of how to implement mobx-react-lite with react hooks. I really like the example of how to implement with the classic way to create stores.

httpjunkie profile image
Eric Bishard

Great article, just learned about 'useReducer' i think observable will be my next hook to learn.

jai_type profile image
Jai Sandhu

Nice writeup! If you were creating a RootStore that contained multiple stores, would you create a single context on the RootStore and share across multiple components via properties?

zlvthisf profile image
zhe lv

wow, inspiring!!!!