All you need is mobx-react-lite
By: Bogdan Birdie
Tags: JavaScript, Mobx, Web Development, Typescript, React

What about bundle size?

Using lightweight packages alternatives is a great way to reduce the final bundle size. And we can do that with many packages. Remember using Moment.js? I don’t recall using it for a while because it has a way bigger bundle size that the alternative Date-fns package. Even tho the Moment still has twice more downloads and stars.

Mobx-react-lite is a lightweight binding to glue Mobx stores and functional React components. And the size of it is smaller, but maybe not as much as you would expect. Nevertheless — this is all we need.

Let’s get started

We will need a React project setup and two dependencies to get started:

yarn add mobx mobx-react-lite OR npm install mobx mobx-react-lite

For a simple example, we can create a Counter Store with some actions and values. I’m using Typescript with the feature enabled to support decorators syntax, but it does not matter if you are using decorators or functions for our case.

In order to access the store from the component we will need to create the instance of the store and, of course, share it in some way with components. React Context is a quite good fit for this task and we can leverage it for our needs. Let’s create a stores.ts file with the store instances and Context wrapper.

Good. Now we have a stores variable to which we can save instances of the Mobx stores. We freeze the object in order to avoid any unexpected changes in it. But, of course, this is an optional step.

We created a React Context based on the store’s variables, and also created a Stores Provider component, we will use it shortly.

Now, let’s update the root index.tsx file with a Context Provider wrapper. Follow this code snippet.

Very well. At this point, we have a place, where we keep our stores. We also have a way to share the stores with the components, but not completely. To access that context we have to create two custom and quite handy hooks. One will return all stores, another — specific store of preference.

Alright, now we have it. See that weird type definition for the useStore hook? It would give us proper types for the passed store key.

<T extends keyof typeof stores>

(store: T): typeof stores[T]

We will only accept store variable type if it’s one of the keys of the stores object. So, in our case, it will only accept a counterStore string and will return the corresponding type of the given store. Nice, isn’t it?

Ok, let’s finally access the store, its methods, and properties from the actual component. To do that we have to modify App.tsx file with the custom hooks and Mobx Observer wrapper.

We access the counter store with it’s key and get the store in return. Also, we have to wrap the component into the observer function to allow the component to listen for the store changes. But still, we do not destruct stores.

const counterStore = useStore("counterStore");

Counter App demo

The app is working as expected, cool! Let’s see the TypeScript hints that we got from this setup and the ways it will cover our back from doing wrong things.

The first thing to mention is the code completion feature. When we will add the useStore hook and start passing a string there as an argument — a key hint will be shown. We also will not be able to pass non-existing store keys. Nice!

TypeScript hint

TypeScript warning

This also works for the case when we have multiple stores as well. We can access them with a separate useStore hook or with a useStores hook as well. Check this out.

TypeScript hint for multiple options

Testing

Sure thing we need to test this. In this article, we won’t make tests for the store itself, since this is a topic of a different nature.

I find it easy enough to use Jest alongside with React Testing Library. So, let’s add the necessary dependencies.

yarn add @testing-library/react-hooks react-test-renderer -D OR npm install @testing-library/react-hooks react-test-renderer --save-dev

Cool! Now we can start testing our hooks file. Nothing too fancy here, but still necessary.

Hooks file tests results

How about component tests?

To do that we will need a few more dependencies. To test the components and to perform user events.

yarn add @testing-library/react @testing-library/user-event -D OR npm install @testing -library/react @testing-library/user-event --save-dev

Good! Let’s test the components now. We can mock the useStore hook to always return a specific store using Jest. And, we can be type-safe with a few extra lines of code. For every test we want the hook to return a new store. But, for one of the tests, we will change that slightly and replace the initial value of the counter. Check this code snippet.

App file tests results

Quite simple, isn’t it? Yep! And we got a green light as well!

Summary

Mobx-react-lite is actually all I need in my personal projects. Would this be your choice of favor as well? Let me know in the comments below 😉.

The entire project is available on the GitHub link.

Thanks for reading this topic!