Jared Palmer has recently shown how to implement Formik with the new and shiny React Hooks. I’ve decided to give the implementation a stab by using MobX instead of the useReducer hook.

You can watch full webinar or just check out Jared’s final work in the CodeSandbox.

What is MobX?

Feel free to skip following paragraphs if you are familiar with MobX.

Unless you have been living in a cave for a past few years, I am sure you have heard something about MobX. I am not going to say it’s better than Redux or any other library. It’s just a different view on state management that can feel a bit magical at first, but less verbose in exchange.

While using Redux (and similar) you have to deal with actions and reducers to produce a new state based on dispatched actions and the previous state. You usually hear that the state should be immutable (mostly for optimization reasons).

MobX on other hand is based on a fully mutable state. Every mutation is tracked internally and can report changes to whoever might be interested in it. MobX can also have actions, but they are merely functions wrapped around direct state mutation.

In my opinion, MobX is not getting enough attention considering it’s actually much simpler to learn for newcomers (I just want to set this property!). Hopefully, this article will help to spread a word a bit more.

Note that currently (February 2019) to use MobX with React Hooks, you have to use a package mobx-react-lite (which I am maintaining) instead of regular mobx-react. That’s something that will most likely change/evolve over time once the dust from Hooks settles.

Launching 3..2..1

If you can, do not try to compare shown solutions here in a matter of LOC (lines of code). While MobX can look shorter and more concise, there is apparent tradeoff with its black-boxy feeling and it might be scary to climb over that hump. But please do try that, it’s not that big pile🗻.

Photo by SpaceX on Unsplash

Tracking form values

If you watch the webinar, Jared is at first showing a simple form with name and email fields and how to easily track values and touched state for these with a help of useReducer from the new React Hooks toolkit. Let’s do that with MobX instead.

Looking closer at the code it’s just a regular functional component with two hooks. The custom reusable hook useFormik takes care of tracking form input values and keeping that state within MobX observable object. There is no need for any nasty switch statements, string actions or merging a value to the previous state 😵.

The somewhat innocent looking useObserver hook is what makes MobX tick in the React world and it will take care of re-rendering when any tracked (a.k.a mentioned) variables change.

You might have heard about useCallback and useMemo optimization tools (Jared mentions it at the very end). Usually, you will use these as the last step in optimization. Or there is an easy way around that with MobX. Instead of useObserver you can use Observer component which ensures that only component UI will be re-rendered. The useFormik hook won’t be re-executed and nothing from there recreated 🙏.

Validate and submit

Let’s fast forward in the webinar where Jared implements logic to handle form submit along with basic validation. Once again, the main difference in a MobX world is that instead of using dispatch with awkwardly named actions you simply mutate the state and let MobX take care of rest.

Have a look at a working example and let’s focus on some parts that are different and tricky.

Note: Enter value “admin” to the Name field to pass the form validation and any value to Email field to pass the submit validation.

Side effects

Executing validation on change of form values sounds like a good idea. With MobX you don’t need to specify explicitly which variables you are depending on; it will figure it out just from the use of observable variables. Note that if props.validate would get updated, that’s a different story and useDisposable allows you to specify inputs in the same way as useEffect.

Scalar state values

And one caveat / bummer / killme effect that even seasoned MobX people might be bumping into from time to time.

The isSubmitting and submitError have to wrapped inside another state object. The problem is that MobX cannot track changes in scalar values (only boxed values). That’s simply a fact and a tradeoff. Since we are spreading formik as an object, only current values would be there and because the hook function is not executed on every change (which is a good thing), it would not see updated values on its own.

React Context

Jared is also showing how to deal with passing the formik object deeper in the tree using React Context. I’ve decided not to tackle that in my examples as it’s not MobX related. I would, however, mention one important fact.

When you have immutable state and you would put that inside the Provider . Whenever a new state is produced, the Provider has to re-render the whole contained tree and that might be rather costly in some cases, eg. rendering a whole form on each keystroke 😮.

In a MobX world with a mutable state, this is not needed. The Provider will always keep a reference to the same state object and as such it does not need to run any rendering logic whatsoever. All updates will happen only inside components that are tracking changes with observers. Isn’t that neat? 😈

Update: I am touching the subject briefly in my other article.

Conclusion

You might be thinking that all that MobX magic must come with a high-performance price tag. Well, it’s definitely higher than a pure functional reducer pattern. However, consider that it does not need to re-render big component trees on every change and suddenly you are getting a great deal of performance back! It might be even faster in more complex scenarios, but I don’t have any benchmarks to prove that.

It’s also worth mentioning that the purpose of the immutable state is to be able to recognize that something has changed in that bulk so you can provide fair optimizations. With MobX you don’t really need to worry about it because it will let you know which parts exactly has changed and what needs to be refreshed because of that. That takes away another huge midstep and allows you to focus purely on what you need to do.

And that’s it. Nothing spectacular I know. I cannot really beat Jared and his awesome presentation 👍. At least I hope you are seriously considering to give the MobX some try. It’s totally worth it!

Questions?

If you want to express your opinion or just ask some questions and you are a bit annoyed by Medium’s way, let’s do that over at Twitter. Kudos to Dan Abramov for this idea used on his overreacted.io blog. Or just use the Spectrum.