Attach Behavior to mobx-state-tree Models Using Actions

Share this video with your friends

Send Tweet
Published 4 years ago
Updated 3 years ago

Models are not just a nifty feature for type checking. They enable you to attach behavior to your actions in a straightforward and highly discoverable way

In this lesson, you will learn:

  • How to define actions on models
  • How to avoid this issues by using self
  • Models can only be modified using actions, and are further read-only from the outside

To learn more about TypeScript check out John Lindquist's wonderful course, Up and Running with TypeScript.

[00:00] Models in MobX State Tree are, by default, read-only. Actions are the only way to modify the properties of a model.

[00:10] Defining actions is done as follows. You create a block called actions and it receives a function. From that function, we will be returning a list of actions. The reason that we use a function with this self parameter is that it prevents issues with divs which are so typical in JavaScript, and often so hard for beginners and even experienced developers.

[00:37] A simple action might look like this. You have an action, change name, which takes a new name, and it's the self property of this name. Notice that we actually have autocompletion here, and that this is thanks to the fact that we are using Visual Studio codes, which tries for default, to enable TypeScript type-checking on the project.

[01:00] MobX State Tree has first-class support for TypeScript. In general, I recommend to use TypeScript. However, for this tutorial I don't, to keep things simple. But please do check out one of the TypeScript Egghead tutorials.

[01:17] We now assign the name with the names passed in, and we now return this function from our action methods, so return a changed name. That makes it possible to invoke it from the outside.

[01:33] Because you could be writing functions over here which are not returned from the action section, this allows you to actually create private methods, which cannot be invoked from the outside. Anyway, let's put this first action to the test.

[01:51] Now this item is not just a piece of data anymore. It now also has methods. Using them, we can change the name. After invoking this method, we know that the name should be Narnia, which is, indeed, the case. Now, we've created models. On those models, we can invoke actions, and they will update the state of the model. A model instance is not purely data anymore. It's also behavior.

[02:21] This might look quite boilerplate-y so far. Luckily, we could write this shorter, thanks to ES6 syntax. We could be returning this object immediately from the function, so we would be writing in it like this. That means an implicit return of objects.

[02:40] In an object we can create a function, like we did. This still works the same. We can even simplify this further, because this is literally the same as just writing object literals with functions.

[02:58] Similarly, we can add some more methods. I know that we need this comma over here, because we're returning an object literal. We now have actions to modify any of these attributes on the wish list item.

[03:15] Let's add a more interesting action. Let's create an action on the wish list that allows us to add new items. Because model instances are mutable objects, we can just take the current items list and put a new item on top of it.

[03:35] However, models are more than just mutable objects, and I'm going to demonstrate that by writing some tests. Let's add a test for this Add method. We have this empty wish list, and now we can call the Add method and we can pass in a new wish list item.

[03:54] The wish list items require a name. I want some book of Chesterton. They require a price. Now we can start again, make some assertions. We expect list.items.length to be one. This obviously works. We can even start chasing that first item to make more clear what we want, and our test still succeeds.

[04:24] In this lesson, we introduced actions. Actions are the only way to modify model instances, which would otherwise be read-only. Actions are exposed by creating a function that returns an object of methods, how it operates on the self arguments, which avoids any budding issues in the future.