Become a member
to unlock all features

    Restore the Model Tree State using Hot Module Reloading when Model Definitions Change

    Michel WeststrateMichel Weststrate

    In this lesson, we will set up Hot Module Reloading(HMR), making it possible to load new definitions for React components and MST models and apply them to a running application.

    In this lesson you will learn:

    • How HMR roughly works
    • How to accept changes to components
    • How to accept changes to changing model definitions, while keeping state


    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson


    Instructor: 00:00 So far we have used local storage to preserve our state, but, actually, we can do something more rad.

    00:06 The downside of the current approach is that, whenever we change something, at least we need to reload the application. For example, if I go to the wish list item view and I want to put a Euro sign in here, you'll notice that our state is nicely preserved, but we also see a full base refresh.

    00:28 There's a technique which we can use to improve this, and that's called hot module reloading. That is a system that might not work in all cases, but we can set it up quite nicely to work for React and mobx-state-tree.

    00:42 Our hot module reloading works roughly like this. Suppose we are modifying this file -- the wish list item view. If you make a modification, webpack sends the change to returning application, and it replaces the module in memory.

    00:58 However, that means that any other module that is depending on that wish list item, for example, a wish list view, needs to be able to handle the fact that a new definition of that module is coming in here.

    01:12 If this file, this wish list view, has not any behavior defined on how to act on this, the change just bubbles up and it bends the tree, so eventually, a change in the wish list item view will end up in our index file. The same holds, of course, for our model definitions. Those changes in these files bubble up the same way.

    01:36 What I'm going to do is I'm going to remove our current local storage implementation, just like this. Then, I'm going to make a function of our initial rendering. I simply wrap that initial render inside a function. For the initial render of the application, I just render it.

    01:57 So far, we didn't really change anything, but now comes the interesting part. I'm going to define this. If we have hot module loading enabled by webpack -- which is, by default, the case in create-react-app -- then there are two cases we need to handle if we have incoming changes.

    02:17 The first case you have to handle is the fact that the app component changes, or one of the components it renders changes. If that is the case, we just want to keep our current state and re-render everything. What we can say is accept changes on this file, so this will also accept any transitive changes in the dependencies of that file.

    02:42 If the component definitions change, we just re-render the application at the root. Since it's still the same wish list being passed in, all the state is preserved. It's just everything is re-rendered in place.

    02:55 The second interesting case is where our model definition changes. These changes we're going to accept, as well. What are we going to do in this case? What we want is to reinstate the entire state tree so that it's according to the new definitions, but we want to preserve our current state.

    03:15 This is, again, something where we can leverage snapshots. We can simply extract the current snapshots from the wish list. Then we say the wish list is now a newly created wish list, based on the new definition which has been injected by webpack, based on the old snapshots.

    03:34 Once we did that, we make sure to re-render the application, so that the new wish list gets passed down the component tree. I just have to make this a variable, so it can change over time. I didn't import getSnapshot yet. If we're now going to make the same change again, I'm reinserting the error sign here, we see that the components nicely update, but that no state is lost and no base reload takes place.

    04:02 Of course, there's also the case where we want to modify a model. Let's say that we have a different calculation for a total price and we will now include their taxes. The VAT rate in Ireland is 20 percent, so let's incorporate that. You see that this total price is now computed from the new definition of our total price.

    04:26 We can change our models on the fly, don't reload anything, and still preserve all the states in the state tree.