Mobx is a state management solution for JavaScript apps. It lets us observe values from a store and then set the values, which will be immediately reflected in the store.
In this article, we’ll look at how to create and use Observable Maps with Mobx.
Observable Maps
Observable maps are a collection of key-value pairs that we can get and set. The value changes can be watched.
To create an Observable map, we can use the observable.map
method as follows:
import { observable, autorun } from "mobx";
const values = {
foo: 1,
bar: 2
};
const observableMap = observable.map(values);
autorun(() => console.log(observableMap.toJS()));
In the code above, we defined an Observable map by creating an values
object and then passing in values
into the observable.map
method.
It also optionally takes a second argument to specify various options.
We can also pass in an ES6 JavaScript Map
instance as follows:
import { observable, autorun } from "mobx";
const values = new Map([["foo, 1"], ["bar", 2]]);
const observableMap = observable.map(values);
autorun(() => console.log(observableMap.toJS()));
In both examples, the autorun
function watches the value of the Observable map as it changes.
It’ll log the value when it’s created in both examples.
A Mobx Observable map has the same methods as an ES6 Map and more. They’re the following:
has(key)
— returns whether a map has an entey with the provided key.set(key, value)
— sets the givenkey
tovalue
. The provided key will be added to the map if it doesn’t exist yetdelete(key)
— deletes the given key and its value from the mapget(key)
— returns the value at the given key orundefined
if thekey
isn’t foundkeys()
— returns an iterator to iterate through all the keys in a map in the order that they’re insertedvalues()
— returns an iterator to iterate through all values present in the map in the order that they’re inserted.entries()
— returns an iterator to iterate through all key-value pairs in the map with each entry being an array with the key and value.forEach(callback)
— runs the callback for each key/value pair in the mapclear()
— removes all entries from a mapsize
— returns the number of entries in a maptoJS()
— converts an Observable map to a normal maptoJSON()
— returns a shallow plain object representation of the map. We can usemobx.toJS(map)
to deep copy a mapintercept(interceptor)
— registers an interceptor that’ll be triggered before any changes are applied to the mapobserve(listener, fireImmediately?)
— attaches a listener that listens to changes in the mapmerge(values)
— copy all entries from the provided object into the mapreplace(values)
— replaces the entire contents of the map with the provided values.
Options
The second argument takes some options to modify the Observable map’s behavior.
We can pass in { deep: false }
to create a shallow map to prevent a nested Observable map from being created.
For example, if we write:
import { observable, autorun } from "mobx";
const values = {
foo: 1,
bar: {
baz: 2
}
};
const observableMap = observable.map(values);
autorun(() => console.log(observableMap.toJS()));
We get a nested Observable map since we have a nested object. The value of bar
is an Observable map.
On the other hand, if we write:
import { observable, autorun } from "mobx";
const values = {
foo: 1,
bar: {
baz: 2
}
};
const observableMap = observable.map(values, { deep: false });
autorun(() => console.log(observableMap.toJS()));
Then we get the plain object:
{
baz: 2
}
as the value of bar
.
Another option is the { name: "my map" }
option, which names the Observable map so we can identify it when we’re debugging with MobX dev tools.
Conclusion
We can create maps that are observable with MobX. It’s like a regular JavaScript map except that it has additional methods.
Also, we can watch is value and manipulate it like a regular map.
By default, Observable maps are recursive, so the values of an Observable map entry may also be an Observable map. We can set the deep
option to false
to disable this behavior and then the nested values will become a plain object.