State Management in React Native for Mac With MobX Library
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Building React Native Apps for Mac course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Building React Native Apps for Mac, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
[00:00 - 00:11] Hi, welcome to the second module for course. In this lesson we will actually start writing the code for our application and we're going to start with state management.
[00:12 - 00:35] That's a little bit counterintuitive rather than starting with the user interface because I think state management is easier if you separate it from React. That is, React comes with a certain way of dealing with state but it kind of mixes a state with the way the UI is rendered so that makes it hard to reason about.
[00:36 - 00:40] So I'd rather start with that. So we're going to use MOBEX.
[00:41 - 00:50] MOBEX is a library based on the observer pattern. So here I am on the MOBEX website and you can see this kind of this small graph .
[00:51 - 01:16] So basically on MOBEX you have certain events that trigger actions, those actions update an observable state. The change in your state notifies the computed values which recalculate themselves and those trigger side effects like rendering or rerunning a function and other stuff.
[01:17 - 01:28] So basically the main piece of the puzzle are observables. An observable is nothing more than an abstraction around a basic value.
[01:29 - 01:47] So once you have a value you wrap it into an observable and that makes it, that enables it for it to be observed by other objects and other functions. So if you're a native Swift developer, maybe you have worked with a combined framework.
[01:48 - 01:55] So it's the same idea. So MOBEX is traditionally used with classes.
[01:56 - 02:05] Here on the website you can see the first example that they give you is with a class but we're going to use factory functions. That's going to make our life a little bit easier.
[02:06 - 02:20] So let's just set up our first piece of code and then we will go over the properties a little bit more into detail. So I'm just going to start setting up a root store.
[02:21 - 02:26] A root store. It's going to be the entry point for all of our state.
[02:27 - 02:36] So I'm just going to go into our application and on the source folder I'm going to create a new file. It's going to be called store.tsx.
[02:37 - 02:51] I'm just going to take the code in the lesson and I'm just going to paste it into this file. So let's just walk over it.
[02:52 - 03:00] First I import a create UI store function which is not there. We're going to create it in a little bit but it again follows the same pattern.
[03:01 - 03:18] This is a factory function for a specific store. Then I'm going to declare a root store type or an interface which is going to help the Type3 compiler figure out all the types.
[03:19 - 03:39] The problem is that we cannot derive all the types from our small stores because they depend on the root store. And we cannot derive the type of the root store without creating the smaller stores.
[03:40 - 03:50] So it kind of records it problem. So we're just going to give the compiler a hand and just tell it, you know, this is our UI store, its return type is whatever this function declares.
[03:51 - 03:58] So we're just giving the compiler a hand here. Then we have our main function.
[03:59 - 04:04] This is where we're going to create the instance itself of our root store. So here you can see it.
[04:05 - 04:08] We have the store. It's just an empty object for now.
[04:09 - 04:24] And we declare it as any because once we return it the type the Type3 compiler is going to figure out on its own. So then we create a new property and we actually call our UI store and we pass our root store instance.
[04:25 - 04:35] Right? So this is so that the smaller stores have access to all the global state or to the other stores so they can call another function, they can talk to each other.
[04:36 - 04:45] And finally we return the instance of the store. So we will also import a final instance.
[04:46 - 04:53] This is the one that we're going to use on our main application. And we could have just created this on the module level without a function.
[04:54 - 04:58] But by putting this into a function that makes it nicer for testing. Right?
[04:59 - 05:21] If at some point we need to create an empty root store, we can just call this function and not worry about how the module has been loaded or any other stuff. So before moving on, let's just go back to the lesson a little bit and let's talk about computed properties in actions.
[05:22 - 05:31] So an observable is fairly straightforward. It's just a wrapper that runs a simple object or a simple value which can be observed.
[05:32 - 05:40] But we haven't talked a lot about observers. So observers can be their computer properties or react components.
[05:41 - 05:47] Computer properties are just that. They're properties that get computed, derived from observables.
[05:48 - 05:57] So in the JavaScript world and in Mobx, they're just functions. So functions are observers of any observable used inside of them.
[05:58 - 06:13] This means whenever a function that uses an observable inside of it, whenever that observable changes, the function is going to rerun itself. So here's a nice example in a completely different context of how this is supposed to work.
[06:14 - 06:21] And this was actually how Mobx was created. So on Microsoft Excel, you have probably worked with it.
[06:22 - 06:31] You have cells with values. And on different cells, you can actually create some formulas which are dependent on other cells.
[06:32 - 06:42] So whenever I change any of the values that fit into this formula, this cell gets recalculated. So that was the base idea that inspired Mobx.
[06:43 - 06:50] That's basically how it works. So the last part of the puzzle are actions.
[06:51 - 07:00] So the problem with observables in JavaScript is that things can get out of sync. You could be calculating some result based on the observables.
[07:01 - 07:06] And then the observable can change. So then your state is not consistent.
[07:07 - 07:12] The final value is not reflected in the state. So that's what actions are.
[07:13 - 07:21] Actions just kind of prevent these race conditions and make sure that there's order to the operations. You update the observable, you calculate it until that calculation is finished.
[07:22 - 07:24] You cannot do anything else. Great.
[07:25 - 07:35] So that's the very high level overview of Mobx. So let's now go into how to use the observables.
[07:36 - 07:42] Mobx has a fairly simple API. The latest version has made it quite a lot simpler.
[07:43 - 07:55] So we're just going to use a single function that's called makeout observable. So makeout observable takes an object and it's going to enhance all the properties in this object.
[07:56 - 08:09] So non-function properties, numbers, arrays, objects, etc., they're going to become observables. Gathers, which are special JavaScript functions, they're going to become computer properties.
[08:10 - 08:22] And any other function is going to become an action. So now comes the time where we'll create our first Mobx store, proper Mobx store.
[08:23 - 08:34] So I'm just going to take this file and back in our project, I'm going to create a new folder. I'm going to call it stores.
[08:35 - 08:46] Here I'm going to create a ui store.ts file and I'm just going to paste it. Let me just quickly fix this import.
[08:47 - 08:53] Great. So we're still kind of missing a little bit of things.
[08:54 - 08:59] Namely, we need Mobx and React bindings. So I'm just going to go to the terminal.
[09:00 - 09:05] I'm just going to do it inside of VS code. I'm going to do yarn at Mobx and Mobx React Lite.
[09:06 - 09:16] So Mobx is the library and Mobx React Lite is the bindings for the React component. Great.
[09:17 - 09:25] So let's just go over the store a little bit. So first we're going to import the makeout observable function from Mobx.
[09:26 - 09:47] Then we're going to import our type from a root store and we can finally create the main function for our store. So it's going to take an instance of the root store, which is going to make it so that this store will be able to access any future stores.
[09:48 - 10:02] Inside of it, we will create the instance of the store itself by calling make out observable and we pass an object to it. So this object has a books array inside of it.
[10:03 - 10:07] It's fairly simple. It's just titled and I created that string.
[10:08 - 10:19] So makeout observable is going to take this property and make it an observable property. Then we have get your case books function.
[10:20 - 10:31] This is going to be a computed property because inside of it, we're using the, you know, the books array. So we're just going to take the books array and we're going to map over it.
[10:32 - 10:44] That means we're going to take each book and apply a function to it. We're going to keep all the properties of the book, but the title, we're going to uppercase it.
[10:45 - 11:00] And we just need to give the compiler a little bit of a hand here and we need to declare the type of the return, the return function, which is just the same book array. The title is just going to be uppercase.
[11:01 - 11:30] And finally, we have the ad book function, which is going to take a title and we're just going to push inside of our book array, a new book, which is just an object with a title and a new creation date. So if we go back to our store, we can see that the import error is gone because we have now our UI star created.
[11:31 - 11:47] And we can finally start connecting our react state or react UI to our stores. In order to do this, we're I'm going to add just a little bit more variables into our root store.
[11:48 - 12:01] I'm just taking them from the lesson and let me just feel the missing import. So these are context.
[12:02 - 12:11] It's a mechanism of react itself to share values. So I'm creating a context, which is going to hold our root store.
[12:12 - 12:28] A provider, we're going to see in a little bit how that's used and a hook function that we're going to use inside of our components to take the root store from the context. So it's just a function, it doesn't take any parameters.
[12:29 - 12:47] And we just say use context and we pass the store context that we created before. So I'm going to go back into the app.tss file and I'm going to take one more time from the lesson, the code.
[12:48 - 12:57] I'm just going to paste it in here. So basically the thing that has changed is that we're now importing a books component from a container.
[12:58 - 13:05] We're going to talk more about containers afterwards, but this is just a React component. We're going to create it in a little bit.
[13:06 - 13:21] Afterwards, I import my root store instance and my store provider from the store file I just created. Inside of it, the first component that I'm going to use is the store provider.
[13:22 - 13:26] As a value, I'm going to pass the instance of my root store. This already has it.
[13:27 - 13:35] If you take a look into when we declared it, we already passed it, but the types are declared like this. So I'm just going to pass it again or too much about it.
[13:36 - 13:42] And inside of it, I'm going to use my books component, my books container. It's fairly simple for now.
[13:43 - 13:47] So let's just go and create our books container. So I'm going to create a new folder in here.
[13:48 - 13:57] I'm going to call it containers. Then I'm going to create my books.container.tss file.
[13:58 - 14:07] Once again, I'm just going to take the code from the lesson. Right.
[14:08 - 14:12] So let's just go over it. First I import React so I can use JSX.
[14:13 - 14:26] Then I'm going to import the observer function. So this enhances React components to act like any other server function whenever one of the observables inside of the component changes, the component is going to re- render itself.
[14:27 - 14:37] Next, I import some React Native components. And finally, I import my use store hook function from the store file.
[14:38 - 14:53] So my books component is just a functional component and I enhance it by calling observer on it. Inside of it, I have my root store, which I get by calling the use store function.
[14:54 - 15:02] And finally, I can return some UI components. So inside of this, you can see I access the root store.
[15:03 - 15:09] Inside of it, I access the UI store. And finally, I access the uppercase books.
[15:10 - 15:17] And finally, I map through them so I can display them in my UI. I take each book, put it inside the view.
[15:18 - 15:25] I need a key. This is just some React Native key that it needs to render the UI.
[15:26 - 15:36] Finally a text component where I just show the book title. I have also added a button with a simple add button title just so we can make sure everything is working.
[15:37 - 15:47] Inside of it is just a hardcoded function where I just call the add book action with a hardcoded value. So let me just save these two files.
[15:48 - 15:53] And now if we start our app, everything should be working. I'm just going to do it inside of VS Code.
[15:54 - 16:04] You can do it inside of your terminal or whatever you want. And there you go.
[16:05 - 16:12] Our books from our UI store are displayed on our UI. And if I click on the add button, it should add more values.