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)
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?
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 yourToasterStore
by creating aRootStore
as described in this articleAfter 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.
I have question.
TodoStore.js
could create new Todos object and exports it. Andindex.js
could simply import thatstore
and use it (I test it and it works).Is there any reason why use
useContext
if it works without it?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
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?
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.
Great article, just learned about 'useReducer' i think observable will be my next hook to learn.
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?
wow, inspiring!!!!