Welcome to our source speech repository about mobx-state-tree and powerpuffs.
- All the information is in the README π
- Source code of our livecoding is described here too ! π
- Feel free to open issues / PR π€
Final application link : https://powerpuff.herokuapp.com/
This is about creating our first model
#30 - Create the first model and instanciate it
Writing our first model of Powerpuff is pretty simple. We'll call it
Powerpuff
(damn, clever π€)
- Import
types
frommobx-state-tree
, this is the most common used API types
is used to ... type fields π, we can also use it to describe models ! Andtypes.model
is the way to go !- Here we create a model with only one field, a
name
which is a string ! - Ok, let's instanciate our model with
Powerpuff.create({})
Powerpuff
is our modelcreate
means we instanciate a new tree, a new instance{}
is the snapshot, the raw data, to use to instanciate a new powerpuff !
- Let's print it with a
console.log
!- As you can see, we use
powerpuff.toJSON()
to convert our tree to a snapshot
- As you can see, we use
- π€ oups, it doesn't work at all ! This is because, by default, a field is required
- Let's instanciate our powerpuff, it will be... hm...
Rebelle
(the french name of Buttercup) - Print it
- It works π
#31 - Make fields optional
Sometimes we don't want fields to be required at creation
- To do so, we can use the type
maybe
, which sets the field tonull
if it's not defined - So now, when we instanciate our powerpuff with an empty snapshot, it works !
- And if we want to instanciate the model with a valued name, we still can do it π
#32 - Use more complex types
There are lots of available types provided by mobx-state-tree, find the entire list in the documentation
- Because a Powerpuff is not only a name but also has feelings π‘π, we add the field
mood
to describe her - Powerpuffs' personalities are simple thus possibilities are limited. Let's use an enumeration to define them
- If you try to create a Powerpuff with a mood which is not in the enumeration, it fails (Don't try to counterfeit a Powerpuff πͺ)
- Use a mood of the enumeration and now you can instanciate a new Powerpuff !
This is how we update our model
#33 - Updating the model, the natural way
As you must be aware, Buttercup is more
aggressive
rather thanhappy
. But the powerpuff is now instanciated, the damage is done. The unique solution to repair this mistake is to modify the instance.
- The natural way would be to set directly the
mood
attribute of the instance - As you can guess, it crashes π₯
#34 - Updating the model, mobx-state-tree way
To mutate the model, mobx-state-tree wants you to create an action. That way mobx-state-tree can create snapshots and the immutability of the state is kept π
- Describe the action within the function
actions
called on the model - We give a callback to
actions
function. This callback takesself
as parameter, it represents the instance itself. The function returns an object of defined actions - Here our action is very simple : we set the
mood
field of the instance with the givenmood
- Use this action to modify the instance, it works π
There are functions that return values deduced from attributes: this is what we call views
#35 - Create a view
Do you know how old is our Powerpuffs now ?
- The best way to know is to add a
birthday
field to our model and then deduce the age from it π‘ - Btw, you can assign a value to a field when you create the model and mobx-state-tree will deduct the types like a grown up π
- Now we can create a view which computes the actual age of our powerpuff. Use the function
views
on the model to describe it - Like actions, views is given a callback which takes
self
as parameter and return an object of functions computing results - Here we write a simple getter to have the current age of the powerpuff and use it like an attribute
- Calling this view on the instance gives us the current age of the powerpuff π
- Note that when we print the powerpuff, her age isn't part of the snapshot but it's memoized by mobx-state-tree
It can be handy to do some computing during the model lifecycle. mobx-state-tree exposes lifecycle hooks that you can find in the documentation
#36 - preProcessSnapshot
Instead of injecting a snapshot to create a new Powerpuff, we want to use a string describing her.
preProcessSnapshot
is called before the model instanciation πββοΈ- It takes the snapshot given to create the instance and returns a new snapshot matching the model
- Here we test if the given snapshot is a string
- If no, we assume it's a well formed snapshot and return it
- If yes, we extract the mood and the name and create a new object with this attributes matching the targeted model
- We can now use a sentence to instanciate our powerpuff, far much simpler β¨
#37 - afterCreate
Say we want Powerpuff's name to be always capitalized (it happens to forget to do it at instanciation, yes everybody can be mistaken, even better ones π)
afterCreate
is called after the model instanciation πββοΈ- It should be defined as actions to access the
self
of the instance - Here we simply capitalize the name and the job is done π
With mobx-state-tree, it's possible to define models that depends on others
#38 - Nest models
Now it's easy to create a Powerpuff, they are spreading and it's becoming a mess ! Let's create a store to bring back some order
- We create a new model, which will be our centralized Store, called
Store
(yeah, still clever π€) - This model has a list of powerpuffs as attribute, which is an array of Powerpuff
- You can notice we introduced a new type :
optional
. It's likemaybe
but you can define the default value. Here we want an empty list of powerpuff if the snapshot doesn't have one - The model has also a function to add a new Powerpuff into the list
- Instanciate a store without snapshot, you get a Store with an empty list of Powerpuff π
- Instanciate some powerpuffs using the store action
addPowerpuff
on the store instance and its list of Powerpuff is filled β¨
We have a centralized Store which contains a list of Powerpuffs and we can edit one from its index in the array. What if the edited one is always store.edited ?
#39 - Creating a reference
First of all we add the
edited
field and declare it as a reference
- We create a new field named
edited
which contains the reference to the currently edited Powerpuff π‘. You can see it like a reference which an editing screen can work with - This field is typed
types.reference
of thePowerpuff
model - We create an action to set this field, go on and call it
setEdited
! - Set the first powerpuff as the edited one π
- Print the
store
snapshot - Oups, it doesn't work π
#40 - Reference an identifier
A reference needs an identifier
- We must add an
identifier
to our Powerpuff, a number is fine, let's call it... hm...id
π !! - The
id
is now required, we add it topreProcessSnapshot
as a random number (π€’, this is just for the demo) and to thebelle
Powerpuff instance as an arbitary number - Let's try to print the
Store
snapshot now! - π it works π, you can see the snapshot doesn't copy the value into
edited
field (which is a reference), mobx-state-tree takes care of optimisations, what a good boy πΆ!
We are sick of console.log everywhere, maybe mobx-state-tree can help us ? Yes it can! π Let's see some debugging tools it provides
#41 - onPatch
How can we track each changes done on our store ?
- We import
onPatch
from mobx-state-tree: it allows us to listen to all patches applied to our store. Here we use it to simply print these patches - We remove all the
console.log
and add theonPatch
listener to ourstore
instance, right after we created it - Now as we run the demo and we see patches applied to the
store
printed to the console - You can see π that a patch contains:
- path
- action type
- value
- This is our favorite tool to debug our store π!
#42 - onSnapshot
What if we want to print the complete store snapshot after each mutation ? π€
- Ok this one, the last one, is an easy one!
- Replace all the
onPatch
byonSnapshot
and tada π π!! - You can see on the console, all the
store
's snapshots for each mutation π - This is great and this is what allows mobx-state-tree to behave like a Redux store. You can see a demo from mobx-state-tree repository!
If you like this demonstration/livecoding, you can tweet about it! - @MilletDelphine and @fabienjuif