Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: State Management with MobX

State management libraries are "a dime a dozen" in the React ecosystem. For most simple applications you may not need a separate state management library. But as your app grows in complexity, you might want to reach out and look for a library that can help you reason about complex, event-driven state in your application. Unfortunately, many of the libraries out there are hard to learn and force you to write a lot of tedious, boilerplate code. Enter MobX. MobX is a powerful and yet, simple, state management library that pairs very well with React. In this Guided Lab, you will wire together a React note-taking application using MobX to help you manage application state.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 52m
Published
Clock icon Sep 18, 2024

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    ### Introduction

    In this lab, you are going to learn all about the MobX state management library and how you can use this library to help you manage state in your React applications. It is well known in the JavaScript ecosystem that managing state can get... complex. Because JavasScript is event-driven by design, your applications are constantly needed to update based on user events. The more complex your app becomes, the more potential complexity you have to manage when it comes to the current state of your application. For simpler React applications, it may be enough to manage state locally using the useState hook. But as your application grows, it can really help to outsource the complexity that comes with managing a lot of application state to a state management library – enter MobX.

    MobX does a really good job at taking complex state management and abstracting you away from all of that complexity so that you can focus more on the domain that you are working in. A lot of other state management libraries make you deal with a lot of boilerplate code, but not MobX.

    In the coming steps, you are going to complete a React app for taking notes all while learning how to use MobX in order to:

    • Define observable state
    • Alter state using actions
    • Respond to changes in state (handling side effects)

    It’s important to note that MobX is a JavaScript library that is not directly tied to React but it does work very, very well with React and a lot of React projects use MobX to help manage complex state interactions. This lab is going to have MobX set up in a React application for you already but if you would like to add MobX to an existing React application and play around with it, it’s as simple as running the command npm i mobx mobx-react (assuming your project uses npm).

    While you are following along and building this application, you can view it by selecting the Run button and refreshing your Web Browser tab!

    info> There may be warnings when compiling the development server. You can safely disregard these warnings.

    info> Note: The solution directory contains the final solution. Feel free to view the file(s) in that directory should you get stuck!

  2. Challenge

    ### Defining Observable State

    There are a lot of state management libraries out there. Some of them are specific to React and some of them are generic with different flavors for each popular JavaScript framework out there. MobX is in the latter category. What sets MobX apart from many other state management libraries is that MobX is a functional, reactive state management library. Yes, I know that sounds very fancy and a little complex but the beautiful thing about MobX is that it abstracts away a lot of the complexity involved.

    MobX is a signal-based state management library. So, what is a signal? Well, you can think of a signal as a wrapper around a value that will emit changes in said value over time to interested parties that are listening. And this is the beauty of MobX – you can very easily mark a value as an “observable” value and any consumers of that piece of observable state will be notified and updated accordingly. When MobX has been used to wrap a value in this manner, it will track any changes to that value and let downstream consumers know of the change for you. It is very easy to use MobX to track changes in all manner of objects and values. You can even easily track changes to different properties in classes without tons of boilerplate! MobX has several different ways of marking a value as an observable and you will learn about these methods in the following tasks. There are several different ways to track state in MobX and otherwise create observables. In your React note taking app that you have inherited you need to make sure that you can track changes to properties within your notes so that your app can seamlessly keep up to date with user actions. The easiest way to start tracking state in MobX is by using the makeAutoObservable function. This function will mark all of the properties on a given class as observable values that MobX will thus begin to track.

    Here are some important makeAutoObservable inference rules from the MobX docs:

    • All own properties on the class will become observable
    • All getters on the class will become computeds
    • All setters on the class will become actions

    By using makeAutoObservable you get all of this for free – and more!

    Here is an example of how to use makeAutoObservable with a basic JavaScript class:

    class Car { 
    
      get make() { 
        return this.make; 
      } 
    
     
    
      get make(make) { 
        this.make = make; 
    
      } 
    
      constructor() { 
        makeAutoObservable(this); 
      } 
    

    The above code will ensure that MobX is watching the state of objects created from your Car class – inferring properties, actions, getters and setters just to name a few.

    info> Note: makeAutoObservable cannot be used on classes that have super or that are subclasses. Now that you have the Note class itself hooked with MobX for state management, you need to make sure that the React NoteComponent itself is integrated with the library. This is as easy as using the observer higher-order component that is available from both the mobx-react and mobx-react-lite packages. This higher-order component accepts one of your components as a function input and will return a new component that MobX has decorated with a lot of behind-the-scenes state management “goodness”. At a high level, what MobX does here is subscribe to updates from any observables that are involved in the rendering of your component. So, for your Note component (since you’ve marked it as an observable class using makeAutoObservable) any time one of the properties of a Note changes, the component will re-render accordingly. As you know, React provides a useState hook for helping to manage local, component state. But what if you need to keep track of a an observable from MobX locally? This can be useful when you have an observable class or object that you need to instantiate and keep track of locally within a component. Mobx povides serveral mechanisms for doing this. One of the simplest ways is to keep track of the observable using the useState hook.

    info> Note: If you can write simpler code by note combining the useState hook with local, Mobx observables, then do that! It’s often better to just simply use the useState hook without MobX for simple, local component state Well done! You now have a firm grasp on how to use MobX observables with React in order to keep track of state and re-render components accordingly. This is the first step when it comes to mastering MobX state management.

    In the next step, you’ll learn how to change state using actions!

  3. Challenge

    ### Updating State With Actions

    Of course you’re going to need to change state in your application at some point. Whether the user toggles an option or updates the position of the mouse on the webpage, the state of your app will change and you’ll need to notify MobX of that change. The mechanism by which a change in state takes place is called an action.

    Now, in a lot of state management frameworks, many problems can arise when multiple changes to state are happening simultaneously. MobX handles changes to state in a performant and scalable way by using transactions. A transaction, within the context of MobX, is a mechanism by which you can batch multiple updates to state and guarantee that any reactions you have setup for your state will not run until the transaction is complete (the actions have changed the state). You will learn about reactions in the next step, but for now, just know that all actions are built on top of transactions and that you can safely use actions to change state while ensuring that the change in state is performant. MobX also helps to ensure that changes in state are atomic by enforcing a rule that says that no change in state can happen outside of an action.

    In the following tasks, you are going to use actions to change state in your React application. The makeAutoObservable helper can handle creating all or most of the actions that you need behind the scenes but there are other mechanisms by which you can change state. As you saw in the last task, creating actions is very easy because of makeAutoObservable. But there are ways to create actions outside of classes and objects. If you remember, MobX uses transactions when updating state – you can make your code more performant by updating state transactionally at the outermost level. This is done by using the action function to wrap multiple inner actions. This approach is very handy for event handlers that call multiple actions to update state. For example, you may have an event handler like this:

     (event) => { 
      observableClass.updateStateOne(); 
    
      observableClass.updateStateTwo(); 
    } 
    

    This causes multiple transactions to be run synchronously. By wrapping this function with action, you can run both of these transactions within a single transaction all in one go. So far you’ve seen how to update state synchronously using actions but you can also update state asynchronously using actions as well. Asynchronous code let’s you run a task and wait for it to complete while JavaScript continues to execute other code. It essentially lets you do things in parallel. A great example of how this relates to state management is when you need to perform a long running task such as updating a database or communicating with an HTTP server. Although not an asynchronous state management library specifically, MobX supports updating state within asynchronous code in a very simple manner.

  4. Challenge

    ### Responding to State Changes

    Another key component of many state management libraries out there is a mechanism for handling side effects. For example, let’s say that your user changes the state in such a way that you must fire off an HTTP request after. This is a great example of a side effect. MobX calls these “reactions”. There are two, “types” of side effects in MobX – reactions and computeds. You've seen an example of reactions but what is a “computed”? A “computed” is a derived value that is automatically recomputed when your state changes. These are very useful for things like deriving automatic property values on classes.

    One of the difficult things about reactions, side effects and the like are that many state management frameworks make you do the work when it comes to setting up all of the boilerplate. MobX doesn’t follow this pattern. The library makes writing code to handle side effects largely pain free.

    In this step, you are going to learn all about both reactions and computeds and how to use them to effortlessly respond to changes in your application state. In the next few tasks, you are going to focus on learning about some of the different reactions that are available to you while using MobX. The first reaction to know about is the autorun reaction. The autorun function receives a function as its first parameter. Any observable that is referenced within that function will trigger the function execution. Here is an example: autorun(() => console.log(note.status)). The preceding code says, “Any time this note’s status changes, log the status to the console”. The autorun reaction is perfect when you want to run one-off side effects when an observable emits a new value.

    info> Note: Reactions from MobX are not always necessary. If your code can be more simple by just utilizing the useEffect hook from React proper then, by all means, go that route! Another reaction at your disposal is the aptly named reaction function! Using reaction is like using a more complex version of autorun. The reaction function lets you pass two functions to it. The first function is called the data function. In this function, you can return the data that you want to be passed as the first argument to the second function that you give to reaction. The second function is known as the side effect function. Basically, reaction lets you take an observable, do some processing, and maybe convert that value into another piece of data that you can then use in the side effect function. This is helpful when you have a more complex side effect that you want to execute. Another very useful reaction that MobX provides is the when reaction. This reaction is useful for when you want to run a side effect when a given predicate becomes truthy. The when reaction expects two functions. The first is the predicate function that needs to return a boolean value based on an observable. MobX will run this function any time the observable emits and will run the second, side effect function when the predicate function returns true. Here is an example usage of the when reaction:

    when(
     () => note.isDone,
     () => { // Your side effect will run here }
    )
    

    info> Note: When the when predicate function returns true, MobX will dispose of this reaction! Calling when also returns a “disposer” that you can use to clean up this reaction should it not be needed anymore. The other type of side effect that you will deal with besides reactions are computeds. These are simply accessible values that are automatically computed based on an observable. When you have a class that uses the makeAutoObservable function, you get computeds for free! Any getteron a JavaScript class will automatically be marked as a computed value.

    info> Note: If you are not using makeAutoObservable you can mark a function as computed by referencing it in the makeObservable function. Here is an example for your reference.

  5. Challenge

    ### Conclusion

    Nicely done! You’ve made it to the end of this guided code lab on the MobX JavaScript library as it pertains to the React ecosystem.

    In summary, you learned how to :

    • Get setup with MobX in your React app
    • Create observable state
    • Alter state using actions
    • Respond to changing state using reactions

    Believe it or not, you’ve barely scratched the surface in terms of MobX and React. As follow up to your learning, explore some more advanced topics within the MobX/React ecosystem. Here are a just a few:

    From here, you can be confident when it comes to using MobX to help you manage state in your React applications and libraries. I recommend that you continue your journey learning MobX and React by pursuing both video courses and more guided code labs here, at PluralSight.

Zach is currently a Senior Software Engineer at VMware where he uses tools such as Python, Docker, Node, and Angular along with various Machine Learning and Data Science techniques/principles. Prior to his current role, Zach worked on submarine software and has a passion for GIS programming along with open-source software.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.