Who's interested in seeing a small demo app converted from React state to MobX-State-Tree and MobX-React?

Follow along. 👇
Here's the basic idea -- it's just a little area and perimeter calculator. I might add the diagonal measurement too if I feel like it, later.
And here's the relevant code. Nothing too special, just a couple useStates and simple calculations. The inputs onChange trigger the `setWidth` and `setHeight` functions, which cause a re-render.
To simulate a more complex app, I'm going to refactor these into their own component files.
Here's a DimensionInput component. It lets me abstract the inputs to their own components, but the state is kept at the main app level, because it's used for the calculations.
And here's the Result component. This one is even simpler, because it just renders a value.
So, what's the problem with this? Not much, for such a simple application.

However, look closely and you'll see the outer edge flashing with "Highlight updates" enabled. And why is the "Height" component updating? https://www.loom.com/share/120dc552542e4d9d9e7a011501929e5c
So let's try this with MobX-State-Tree and MobX-React-Lite. 😉
First add the three packages.
Now we'll create a store. These are created with the `types` object, imported from MST.
We need a way to access a single instance of the store in any component. Easiest way is to create a custom hook using useMemo. (You can also use context, but this is my favorite.) We hang onto a reference to the store in `_store` which makes sure we only ever have one.
Having generic DimensionInput and Result components doesn't work as well in this case, so I'm going to move them into their own components. Probably should have thought this through a little better before I started. But I think it'll still show the power of MST pretty well.
We no longer have to rely on props, as we can use the useStore hook to grab the values from the MST store.

(the onChange setters are coming next)
Back in the store, we add a couple of setter actions. In MST, the only place that data can be mutated is in an action. This allows MST to track changes properly.
We can pull these setters into the actions like this, to handle changes to the width and height values.
Now we need a couple of MST "views" to compute the area and perimeter. Views are computed values, so they essentially take data that's already in the store and present it in a different way. In this case, we already have width and height, so we can calculate these.
With those views, we can now make our area and perimeter result components.
Back in the main index.js, we don't have to pass anything through to the inputs or result components, since they all have access to the RootStore.
We need just one more thing to make this all work -- MobX-React-Lite.

With it, we'll make any component that needs to react to changes in the store an "observer".

It's super easy -- just wrap it in the `observer()` function from mobx-react-lite.
Unfortunately, React Dev Tools don't seem to recognize MobX-React-Lite component re-renders. You'll have to take my word for it that only the components that *need* to re-render, are re-rendering.
You might think ... "wait a minute, the previous version was simpler". And it kind of was, for this simple application.
But as your app grows and gets many layers of components deep, you'll love the convenience of the `useStore()` hook, the well-defined structure of your RootStore, and the awesome performance of `observer()`.
Let me know if you have questions -- I'm happy to answer them!
If someone wants to try to implement a diagonal calculation, go for it. The repo has PRs open!
You can follow @jamonholmgren.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled: