Skip to content

Instantly share code, notes, and snippets.

@lostintangent
Last active December 7, 2023 12:55
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save lostintangent/c3bcd4bff4a13b2e1b3fc4a26332e2b6 to your computer and use it in GitHub Desktop.
Save lostintangent/c3bcd4bff4a13b2e1b3fc4a26332e2b6 to your computer and use it in GitHub Desktop.
Learning MobX (Side-Effects)

1: Intro

Welcome to the interactive tutorial on how to use side-effect "operators" in MobX! Over the course of the next three samples, you'll learn (and be able to explore) exactly how autorun, when and reaction work, and when/why you would use them when building reactive applications.

<button id="setLoadingTrue">Set isLoading to true</button>
<button id="setLoadingFalse">Set isLoading to false</button>
<button id="addDynamicProp">Add dynamic prop</button>
{
"title": "Learning MobX (Side-Effects)",
"description": "Learning MobX (Side-Effects)",
"steps": [
{
"file": "script.js",
"line": 11,
"description": "This is cool!"
}
]
}

2: autorun

autorun takes a function, and immediately runs it. Upon execution, it detects any observables that the function accesses (e.g. observable.property), and will automatically re-run the function anytime those observables change.

For example, you should have seen the Loading changed alert display immediately when viewing/running this playground. This is because of the initial autorun call here. If you click either of the two buttons below, you'll see the alert again.

However, if you click the same button multiple times, you won't see the alert, because the observable isn't changing. Try it for yourself!

import { observable, autorun } from "mobx";
const store = observable({
isLoading: false
});
autorun(() => {
alert(`Loading changed: ${store.isLoading}`);
});
autorun(() => {
if (store.newProp) {
alert(`Dynamic property added: ${store.newProp}`);
}
})
document.querySelector("#setLoadingTrue").onclick = () => {
store.isLoading = true;
};
document.querySelector("#setLoadingFalse").onclick = () => {
store.isLoading = true;
};
document.querySelector("#addDynamicProp").onclick = () => {
store.newProp = "Cool!";
};
<button>Update the store</button>

3: when

The when operator allows you to specify a predicate and a callback function. The predicate function will observed it until it returns true. Once true, your callback function is run, and then the observer is disposed.

For example, click the following button to mutate a store property, which should trigger the when handler here. However, if you click it again, it won't trigger the handler again, since the observer has been disposed.

Click the "run playground" button in order to reset the tutorial step and try again.

import { observable, when } from "mobx";
const store = observable({
isLoading: false
});
when(() => store.isLoading, () => {
alert("Loaded! :D");
});
document.querySelector("button").onclick = () => {
store.isLoading = true;
};
<button id="setLoadingTrue">Set isLoading to true</button>
<button id="setLoadingFalse">Set isLoading to false</button>

4: reaction

The reaction operator is similar to autorun, but it allows you to control exactly which observables should be tracked.

It takes two functions: one that determines the observables that should be tracked, and a callback that will be triggered whenever any of the tracked observables as changed.

Unlike autorun the callback is only run after the tracked observables change, as opposed to also being run immediately.

For example, if you click the two buttons below, you should see the Loading changed alert. This is because of the reaction call here. However, if you click the same button multiple times, you won't see the alert, because the observable isn't changing. Try it for yourself!

import { observable, reaction } from "mobx";
const store = observable({
isLoading: false
});
reaction(() => [store.isLoading], () => {
alert(`Loading changed: ${store.isLoading}`);
});
document.querySelector("#setLoadingTrue").onclick = () => {
store.isLoading = true;
};
document.querySelector("#setLoadingFalse").onclick = () => {
store.isLoading = false;
};
{
"tutorial": "Learning MobX (Side-Effects)",
"layout": "splitLeftTabbed",
"readmeBehavior": "previewHeader",
"themePreview": false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment