Categories
Mobx

Creating Observables with Mobx

Spread the love

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 an Observable that lets us subscribe to it and then change the value of it.

The observable Function

The Mobx observable function takes an object. It’s also available in decorator form where we can set the value of it directly.

It can be used as follows:

  • observable(value)
  • @observable classProperty = value

It returns various kinds of values depending on what value is passed in. The value can be JavaScript primitive values, references, plain objects, class instances, arrays, and maps.

There’re some conversion rules applied to values that are passed into the observable function. They’re the following:

  • If value is an ES6 Map , then a new Observable Map will be returned. Observable maps are very useful if we want to react to changes in a specific entry, and addition or removal of entries.
  • If value is an ES6 Set , then a new Observable Set will be returned.
  • If value is an array, then a new Observable array will be returned.
  • If value is an object without a prototype, all its current properties will be made observable
  • If value is an object with a prototype, a JavaScript primitive or function, the observable will throw. We should use Boxed Observable observables instead.

For example, we can use observable as follows:

import { observable } from "mobx";
const map = observable.map({ foo: "value" });
map.observe(({ oldValue, newValue }) => console.log(oldValue, newValue));

map.set("foo", "new value");

In the code above, we have the observable.map function to create an Observable Map.

Then we attach a listener to it to watch the values with the observe function. The listener gives us an object with the oldValue and newValue properties so we can retrieve them.

When we call:

map.set("foo", "new value");

then we’ll see the values logged by the listener.

We can also do something similar with arrays:

import { observable } from "mobx";
const array = observable([1, 2, 3]);
array.observe(({ oldValue, newValue }) => console.log(oldValue, newValue));

array[1] = 5;

We passed in an array to the observable function which returns an Observable array. Then we can call observe on it to watch its values like before.

Then when we make changes to array , the listener then we pass into observe will log the new and old values.

To make primitives observable, we can use the box method as follows:

import { observable } from "mobx";
const num = observable.box(3);
num.observe(({ oldValue, newValue }) => console.log(oldValue, newValue));

num.set(10);

In the code above, we created an observable primitive with the box method. The code for observing the value change is the same as before.

Then we can use set to set a new value for the num Observable primitive.

The @observable Decorator

If our codebase has support for ES7 or TypeScript, then we can use the @observable decorator to make class properties observable.

We can use them as follows:

import { observable, computed } from "mobx";

class Person {
  @observable firstName = "Jane";
  @observable lastName = "Smith";

  @computed get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const person = new Person();
console.log(person.firstName);
console.log(person.lastName);
console.log(person.fullName);

In the code above, we created the Person class which has Observable properties as indicated by using the observable decorator. We also have a computed property fullName which is a getter.

Then we create a new Person instance and we can log the values.

We can also set the values by assigning a value as usual.

To use decorators, we can use a build system like Parcel and then add the @babel/core , @babel/plugin-proposal-class-properties, @babel/plugin-proposal-decorators , and @babel/preset-env packages and all them to .babelrc in the plugins section as follows:

{
  "presets": [
    "@babel/preset-env"
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ]
  ]
}

Conclusion

We can create Observable values with the observable object. It can be used with various kinds of objects as long as it’s used with the correct method to create an Observable value.

Then we can use the observe method to observe the value of the returned Observable and manipulate it.

We can also use the observable decorator with classes to create a class with Observable properties.

To use decorators we either use Babel or TypeScript.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *