### Install MobX
Source: https://mobx.js.org/installation.html
Commands to install MobX using Yarn or NPM.
```bash
yarn add mobx
```
```bash
npm install --save mobx
```
--------------------------------
### Collection utilities example
Source: https://mobx.js.org/collection-utilities.html
Demonstrates the usage of `get`, `values`, and `set` from MobX collection utilities to manage observable objects.
```javascript
import { autorun, get, set, observable, values } from "mobx"
const twitterUrls = observable.object({
Joe: "twitter.com/joey"
})
autorun(() => {
// Get can track not yet existing properties.
console.log(get(twitterUrls, "Sara"))
})
autorun(() => {
console.log("All urls: " + values(twitterUrls).join(", "))
})
set(twitterUrls, { Sara: "twitter.com/horsejs" })
```
--------------------------------
### A quick example
Source: https://mobx.js.org/README.html
This example demonstrates how to use MobX with React to manage state. It includes creating observable state, defining actions to modify it, and using the observer component to automatically re-render when the state changes.
```javascript
import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react-lite"
// Model the application state.
function createTimer() {
return makeAutoObservable({
secondsPassed: 0,
increase() {
this.secondsPassed += 1
},
reset() {
this.secondsPassed = 0
}
})
}
const myTimer = createTimer()
// Build a "user interface" that uses the observable state.
const TimerView = observer(({ timer }) => (
))
ReactDOM.render(, document.body)
// Update the 'Seconds passed: X' text every second.
setInterval(() => {
myTimer.increase()
}, 1000)
```
--------------------------------
### Custom Reaction Example using autorun
Source: https://mobx.js.org/the-gist-of-mobx.html
This example shows how to create a custom reaction using the `autorun` function to log a message whenever the `unfinishedTodoCount` changes.
```javascript
// A function that automatically observes the state.
autorun(() => {
console.log("Tasks left: " + todos.unfinishedTodoCount)
})
```
--------------------------------
### Function props - Tedious setup
Source: https://mobx.js.org/react-optimizations.html
Illustrates the repetitive setup required when creating many small observer components to display specific data fields, leading to code duplication.
```javascript
const PersonNameDisplayer = observer(({ person }) => )
const CarNameDisplayer = observer(({ car }) => )
const ManufacturerNameDisplayer = observer(({ car }) =>
)
```
--------------------------------
### Combining Multiple Stores Example
Source: https://mobx.js.org/defining-data-stores.html
An example demonstrating how to combine multiple stores using a RootStore pattern, with references shared between stores.
```javascript
class RootStore {
constructor() {
this.userStore = new UserStore(this)
this.todoStore = new TodoStore(this)
}
}
class UserStore {
constructor(rootStore) {
this.rootStore = rootStore
}
getTodos(user) {
// Access todoStore through the root store.
return this.rootStore.todoStore.todos.filter(todo => todo.author === user)
}
}
class TodoStore {
todos = []
rootStore
constructor(rootStore) {
makeAutoObservable(this)
this.rootStore = rootStore
}
}
```
--------------------------------
### Timer example
Source: https://mobx.js.org/react-integration.html
A more complete example demonstrating a timer component that updates and re-renders using MobX observables and the `observer` HoC.
```javascript
import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react-lite"
class Timer {
secondsPassed = 0
constructor() {
makeAutoObservable(this)
}
increaseTimer() {
this.secondsPassed += 1
}
}
const myTimer = new Timer()
// A function component wrapped with `observer` will react
// to any future change in an observable it used before.
const TimerView = observer(({ timer }) => Seconds passed: {timer.secondsPassed})
ReactDOM.render(, document.body)
setInterval(() => {
myTimer.increaseTimer()
}, 1000)
```
--------------------------------
### extendObservable example
Source: https://mobx.js.org/api.html
Example of using extendObservable with old-fashioned constructor functions.
```javascript
function Person(firstName, lastName) {
extendObservable(this, { firstName, lastName })
}
const person = new Person("Michel", "Weststrate")
```
--------------------------------
### Lazy Observables Example
Source: https://mobx.js.org/lazy-observables.html
This example demonstrates how to use onBecomeObserved and onBecomeUnobserved to fetch temperature data only when the 'temperature' observable is being observed.
```javascript
export class City {
location
temperature
interval
constructor(location) {
makeAutoObservable(this, {
resume: false,
suspend: false
})
this.location = location
// Only start data fetching if temperature is actually used!
onBecomeObserved(this, "temperature", this.resume)
onBecomeUnobserved(this, "temperature", this.suspend)
}
resume = () => {
log(`Resuming ${this.location}`)
this.interval = setInterval(() => this.fetchTemperature(), 5000)
}
suspend = () => {
log(`Suspending ${this.location}`)
this.temperature = undefined
clearInterval(this.interval)
}
fetchTemperature = flow(function* () {
// Data fetching logic...
})
}
```
--------------------------------
### Transaction Example
Source: https://mobx.js.org/api.html
Demonstrates how to use the `transaction` API to batch updates and defer reactions.
```javascript
import { observable, transaction, autorun } from "mobx"
const numbers = observable([])
autorun(() => console.log(numbers.length, "numbers!"))
// Prints: '0 numbers!'
transaction(() => {
transaction(() => {
numbers.push(1)
numbers.push(2)
})
numbers.push(3)
})
// Prints: '3 numbers!'
```
--------------------------------
### Reactive React Component Example
Source: https://mobx.js.org/the-gist-of-mobx.html
This example demonstrates how to make React components reactive using the `observer` function from `mobx-react-lite`. It shows a `TodoListView` and `TodoView` that automatically re-render based on state changes.
```javascript
import * as React from "react"
import { render } from "react-dom"
import { observer } from "mobx-react-lite"
const TodoListView = observer(({ todoList }) => (
{todoList.todos.map(todo => (
))}
Tasks left: {todoList.unfinishedTodoCount}
))
const TodoView = observer(({ todo }) => (
todo.toggle()} />
{todo.title}
))
const store = new TodoList([new Todo("Get Coffee"), new Todo("Write simpler code")])
render(, document.getElementById("root"))
```
--------------------------------
### Example of makeObservable with decorators
Source: https://mobx.js.org/migrating-from-4-or-5.html
Use makeObservable in the constructor while retaining decorators, allowing it to pick up metadata.
```javascript
makeObservable(this)
```
--------------------------------
### action.bound
Source: https://mobx.js.org/actions.html
Example demonstrating the use of `action.bound` to automatically bind the action to the instance.
```javascript
import { makeObservable, observable, action } from "mobx"
class Doubler {
value = 0
constructor() {
makeObservable(this, {
value: observable,
increment: action.bound
})
}
increment() {
this.value++
this.value++
}
}
const doubler = new Doubler()
// Calling increment this way is safe as it is already bound.
setInterval(doubler.increment, 1000)
```
--------------------------------
### Babel Configuration
Source: https://mobx.js.org/enabling-decorators.html
Example babel.config.json to enable the proposal-decorators plugin.
```json
// babel.config.json (or equivalent)
{
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"version": "2023-05"
}
]
]
}
```
--------------------------------
### Basic autorun example
Source: https://mobx.js.org/understanding-reactivity.html
Demonstrates a basic autorun that logs the title of a message and updates it, showing MobX's reactivity.
```javascript
autorun(() => {
console.log(message.title)
})
message.updateTitle("Bar")
```
--------------------------------
### UI State Store Example
Source: https://mobx.js.org/defining-data-stores.html
An example of a UI state store using ES6 syntax, demonstrating observable properties and computed values.
```javascript
import { makeAutoObservable, observable, computed } from "mobx"
export class UiState {
language = "en_US"
pendingRequestCount = 0
// .struct makes sure observer won't be signaled unless the
// dimensions object changed in a deepEqual manner.
windowDimensions = {
width: window.innerWidth,
height: window.innerHeight
}
constructor() {
makeAutoObservable(this, { windowDimensions: observable.struct })
window.onresize = () => {
this.windowDimensions = getWindowDimensions()
}
}
get appIsInSync() {
return this.pendingRequestCount === 0
}
}
```
--------------------------------
### Autorun example
Source: https://mobx.js.org/reactions.html
Demonstrates how to use autorun and its disposer function to stop a reaction.
```javascript
const counter = observable({ count: 0 })
// Sets up the autorun and prints 0.
const disposer = autorun(() => {
console.log(counter.count)
})
// Prints: 1
counter.count++
// Stops the autorun.
disposer()
// Will not print.
counter.count++
```
--------------------------------
### observable.box example
Source: https://mobx.js.org/api.html
Demonstrates creating an observable box for a primitive value and updating it.
```javascript
import { observable, autorun } from "mobx"
const cityName = observable.box("Vienna")
autorun(() => {
console.log(cityName.get())
})
// Prints: 'Vienna'
cityName.set("Amsterdam")
// Prints: 'Amsterdam'
```
--------------------------------
### Good list rendering example
Source: https://mobx.js.org/react-optimizations.html
This example demonstrates an optimized approach to list rendering by separating the list mapping into a dedicated observer component (TodosView), preventing unnecessary reconciliation of individual items when unrelated data changes.
```javascript
const MyComponent = observer(({ todos, user }) => (
{user.name}
))
const TodosView = observer(({ todos }) => (
{todos.map(todo => (
))}
))
```
--------------------------------
### Autorun Example
Source: https://mobx.js.org/reactions.html
This example demonstrates how to use the `autorun` utility in MobX to create side effects that automatically run when observable state changes. It includes a class `Animal` with observable properties and actions, and two `autorun` functions that log changes to the animal's energy level and hunger status.
```javascript
import { makeAutoObservable, autorun } from "mobx"
class Animal {
name
energyLevel
constructor(name) {
this.name = name
this.energyLevel = 100
makeAutoObservable(this)
}
reduceEnergy() {
this.energyLevel -= 10
}
get isHungry() {
return this.energyLevel < 50
}
}
const giraffe = new Animal("Gary")
autorun(() => {
console.log("Energy level:", giraffe.energyLevel)
})
autorun(() => {
if (giraffe.isHungry) {
console.log("Now I'm hungry!")
} else {
console.log("I'm not hungry!")
}
})
console.log("Now let's change state!")
for (let i = 0; i < 10; i++) {
giraffe.reduceEnergy()
}
```
--------------------------------
### Example of makeAutoObservable
Source: https://mobx.js.org/migrating-from-4-or-5.html
Use makeAutoObservable in the class constructor to automatically observable fields and methods.
```javascript
makeAutoObservable(this)
```
--------------------------------
### toJS Example
Source: https://mobx.js.org/api.html
Demonstrates how to use the `toJS` function to convert an observable object into a plain JavaScript object.
```javascript
const obj = mobx.observable({
x: 1
})
const clone = mobx.toJS(obj)
console.log(mobx.isObservableObject(obj)) // true
console.log(mobx.isObservableObject(clone)) // false
```
--------------------------------
### makeObservable
Source: https://mobx.js.org/actions.html
Example of using `makeObservable` with `observable` and `action` decorators for state and methods.
```javascript
import { makeObservable, observable, action } from "mobx"
class Doubler {
value = 0
constructor() {
makeObservable(this, {
value: observable,
increment: action
})
}
increment() {
// Intermediate states will not become visible to observers.
this.value++
this.value++
}
}
```
--------------------------------
### MobX Fallback for Older JavaScript Environments
Source: https://mobx.js.org/installation.html
Configuration to explicitly enable the ES5 fallback implementation for MobX when Proxies are not available.
```javascript
import { configure } from "mobx"
configure({ useProxies: "never" }) // Or "ifavailable".
```
--------------------------------
### Vite Configuration
Source: https://mobx.js.org/enabling-decorators.html
Example vite.config.js to configure Babel plugins for decorators.
```javascript
// vite.config.js
{
plugins: [
react({
babel: {
plugins: [
[
"@babel/plugin-proposal-decorators",
{
version: "2023-05"
}
]
]
}
})
]
}
```
--------------------------------
### Babel Configuration for Class Properties
Source: https://mobx.js.org/installation.html
Configuration for Babel (versions < 7.13.0 and >= 7.13.0) to ensure spec-compliant transpilation for class fields.
```json
{
// Babel < 7.13.0
"plugins": [["@babel/plugin-proposal-class-properties", { "loose": false }]]
}
```
```json
{
// Babel >= 7.13.0 (https://babel.js.io/docs/en/assumptions)
"plugins": [["@babel/plugin-proposal-class-properties"]],
"assumptions": {
"setPublicClassFields": false
}
}
```
--------------------------------
### makeObservable with accessor
Source: https://mobx.js.org/actions.html
Example using `makeObservable` with `observable accessor` and `@action` decorator.
```javascript
import { observable, action } from "mobx"
class Doubler {
@observable accessor value = 0
@action
increment() {
// Intermediate states will not become visible to observers.
this.value++
this.value++
}
}
```
--------------------------------
### Observable State Example
Source: https://mobx.js.org/the-gist-of-mobx.html
Defines a Todo class with observable properties (title, finished) and an action (toggle).
```javascript
import { makeObservable, observable, action } from "mobx"
class Todo {
id = Math.random()
title = ""
finished = false
constructor(title) {
makeObservable(this, {
title: observable,
finished: observable,
toggle: action
})
this.title = title
}
toggle() {
this.finished = !this.finished
}
}
```
--------------------------------
### Legacy Decorators with makeObservable
Source: https://mobx.js.org/enabling-decorators.html
Example of using legacy decorators with the 'makeObservable' utility.
```typescript
import { makeObservable, observable, computed, action } from "mobx"
class Todo {
id = Math.random()
@observable title = ""
@observable finished = false
constructor() {
makeObservable(this)
}
@action
toggle() {
this.finished = !this.finished
}
}
class TodoList {
@observable todos = []
@computed
get unfinishedTodoCount() {
return this.todos.filter(todo => !todo.finished).length
}
constructor() {
makeObservable(this)
}
}
```
--------------------------------
### action.bound with makeAutoObservable
Source: https://mobx.js.org/actions.html
Example demonstrating the use of `makeAutoObservable` with `autoBind: true` to automatically bind all actions and flows.
```javascript
import { makeAutoObservable } from "mobx"
class Doubler {
value = 0
constructor() {
makeAutoObservable(this, {}, { autoBind: true })
}
increment() {
this.value++
this.value++
}
*flow() {
const response = yield fetch("http://example.com/value")
this.value = yield response.json()
}
}
```
--------------------------------
### Observe all fields
Source: https://mobx.js.org/intercept-and-observe.html
This example demonstrates how to observe all fields of an observable object and log changes. It also shows how to dispose of the observer.
```javascript
import { observable, observe } from "mobx"
const person = observable({
firstName: "Maarten",
lastName: "Luther"
})
// Observe all fields.
const disposer = observe(person, change => {
console.log(change.type, change.name, "from", change.oldValue, "to", change.object[change.name])
})
person.firstName = "Martin"
// Prints: 'update firstName from Maarten to Martin'
// Ignore any future updates.
disposer()
// Observe a single field.
const disposer2 = observe(person, "lastName", change => {
console.log("LastName changed to ", change.newValue)
})
```
--------------------------------
### Sharing observables using React Context
Source: https://mobx.js.org/react-integration.html
An example demonstrating how to share observables with an entire React subtree using Context.
```javascript
import {observer} from 'mobx-react-lite'
import {createContext, useContext} from "react"
const TimerContext = createContext()
const TimerView = observer(() => {
// Grab the timer from the context.
const timer = useContext(TimerContext) // See the Timer definition above.
return (
Seconds passed: {timer.secondsPassed}
)
})
ReactDOM.render(
,
document.body
)
```
--------------------------------
### Working with References
Source: https://mobx.js.org/getting-started
Example demonstrating how to assign references between observable objects and how MobX tracks these changes automatically.
```javascript
const peopleStore = observable([
{
name: "Michel"
},
{
name: "Me"
}
]);
observableTodoStore.todos[0].assignee = peopleStore[0];
observableTodoStore.todos[1].assignee = peopleStore[1];
peopleStore[0].name = "Michel Weststrate";
```
--------------------------------
### Interacting with the TodoStore
Source: https://mobx.js.org/getting-started
Demonstrates adding todos, logging the report, marking a todo as completed, and modifying existing todos to observe changes.
```javascript
todoStore.addTodo("read MobX tutorial");
console.log(todoStore.report());
todoStore.addTodo("try MobX");
console.log(todoStore.report());
todoStore.todos[0].completed = true;
console.log(todoStore.report());
todoStore.todos[1].task = "try MobX in own project";
console.log(todoStore.report());
todoStore.todos[0].task = "grok MobX tutorial";
console.log(todoStore.report());
```
--------------------------------
### Custom Observable Clock Example
Source: https://mobx.js.org/custom-observables.html
This example demonstrates how to create a custom observable 'Clock' using MobX's `createAtom` function. The clock ticks and updates its time only when it's being observed by a MobX reaction. It includes methods to start and stop ticking, and to report observed and changed states to MobX.
```javascript
import { createAtom, autorun } from "mobx"
class Clock {
atom
intervalHandler = null
currentDateTime
constructor() {
// Creates an atom to interact with the MobX core algorithm.
this.atom = createAtom(
// 1st parameter:
// - Atom's name, for debugging purposes.
"Clock",
// 2nd (optional) parameter:
// - Callback for when this atom transitions from unobserved to observed.
() => this.startTicking(),
// 3rd (optional) parameter:
// - Callback for when this atom transitions from observed to unobserved.
() => this.stopTicking()
// The same atom transitions between these two states multiple times.
)
}
getTime() {
// Let MobX know this observable data source has been used.
//
// reportObserved will return true if the atom is currently being observed
// by some reaction. If needed, it will also trigger the startTicking
// onBecomeObserved event handler.
if (this.atom.reportObserved()) {
return this.currentDateTime
} else {
// getTime was called, but not while a reaction was running, hence
// nobody depends on this value, and the startTicking onBecomeObserved
// handler won't be fired.
//
// Depending on the nature of your atom it might behave differently
// in such circumstances, like throwing an error, returning a default
// value, etc.
return new Date()
}
}
tick() {
this.currentDateTime = new Date()
this.atom.reportChanged() // Let MobX know that this data source has changed.
}
startTicking() {
this.tick() // Initial tick.
this.intervalHandler = setInterval(() => this.tick(), 1000)
}
stopTicking() {
clearInterval(this.intervalHandler)
this.intervalHandler = null
}
}
const clock = new Clock()
const disposer = autorun(() => console.log(clock.getTime()))
// Prints the time every second.
// Stop printing. If nobody else uses the same `clock`, it will stop ticking as well.
disposer()
```
--------------------------------
### Example of a React component rendering a specific Item
Source: https://mobx.js.org/computeds-with-args.html
This code snippet demonstrates a basic MobX setup with a React component that needs to determine if an item is selected.
```javascript
import * as React from 'react'
import { observer } from 'mobx-react-lite'
const Item = observer(({ item, store }) => (
{item.title}
))
```
--------------------------------
### Direct State Mutation Example
Source: https://mobx.js.org/getting-started
Demonstrates directly mutating the MobX store's state to trigger UI updates, highlighting MobX's automatic reactivity.
```javascript
const store = observableTodoStore;
store.todos[0].completed = !store.todos[0].completed;
store.todos[1].task = "Random todo " + Math.random();
store.todos.push({ task: "Find a fine cheese", completed: true });
// etc etc.. add your own statements here...
```
--------------------------------
### Interacting with the Observable Store
Source: https://mobx.js.org/getting-started
Demonstrates how actions on the observable store trigger automatic updates and re-execution of the autorun function.
```javascript
observableTodoStore.addTodo("read MobX tutorial");
observableTodoStore.addTodo("try MobX");
observableTodoStore.todos[0].completed = true;
observableTodoStore.todos[1].task = "try MobX in own project";
observableTodoStore.todos[0].task = "grok MobX tutorial";
```
--------------------------------
### Using DisposableStack example
Source: https://mobx.js.org/reactions.html
Shows how to use DisposableStack with reactions in environments supporting Explicit Resource Management for simultaneous disposal.
```javascript
function createSomeDisposableResource() {}
class Vat {
value = 1.2
constructor() {
makeAutoObservable(this)
}
}
const vat = new Vat()
class OrderLine {
price = 10
amount = 1
disposableStack = new DisposableStack()
someDisposableResource
constructor() {
makeAutoObservable(this)
this.disposableStack.use(autorun(() => {
doSomethingWith(this.price * this.amount)
}))
this.disposableStack.use(autorun(() => {
doSomethingWith(this.price * this.amount * vat.value)
}))
this.someDisposableResource = this.disposableStack.use(createSomeDisposableResource())
}
[Symbol.dispose]() {
this.disposableStack[Symbol.dispose]();
}
}
```
--------------------------------
### Asynchronous Actions
Source: https://mobx.js.org/getting-started
Example of handling asynchronous actions in MobX, including updating UI state during loading and processing mutations within an action.
```javascript
observableTodoStore.pendingRequests++;
setTimeout(action(() => {
observableTodoStore.addTodo('Random Todo ' + Math.random());
observableTodoStore.pendingRequests--;
}), 2000);
```
--------------------------------
### Input Box HTML
Source: https://mobx.js.org/getting-started
The HTML for the input box used to demonstrate changing a name reference.
```html
```
--------------------------------
### Dereferencing values late - Faster example
Source: https://mobx.js.org/react-optimizations.html
This example demonstrates a more performant approach where data is passed down to a component that dereferences it, minimizing re-renders in parent components.
```javascript
```
--------------------------------
### Bad list rendering example
Source: https://mobx.js.org/react-optimizations.html
This example shows a suboptimal way to render lists where changes in unrelated data (user.name) can cause unnecessary reconciliation of all TodoView components.
```javascript
const MyComponent = observer(({ todos, user }) => (
{user.name}
{todos.map(todo => (
))}
))
```
--------------------------------
### Observable Array Example
Source: https://mobx.js.org/observable-state.html
Demonstrates creating an observable array and observing it with autorun. Also shows working with Map and Set collections.
```javascript
import { observable, autorun } from "mobx"
const todos = observable([
{ title: "Spoil tea", completed: true },
{ title: "Make coffee", completed: false }
])
autorun(() => {
console.log(
"Remaining:",
todos
.filter(todo => !todo.completed)
.map(todo => todo.title)
.join(", ")
)
})
// Prints: 'Remaining: Make coffee'
todos[0].completed = false
// Prints: 'Remaining: Spoil tea, Make coffee'
todos[2] = { title: "Take a nap", completed: false }
// Prints: 'Remaining: Spoil tea, Make coffee, Take a nap'
todos.shift()
// Prints: 'Remaining: Make coffee, Take a nap'
```
--------------------------------
### React Components with MobX Observer
Source: https://mobx.js.org/getting-started
Defines React components (TodoList and TodoView) wrapped with MobX's `observer` to make them reactive to state changes. Includes examples of state manipulation within components and rendering lists.
```javascript
const TodoList = observer(({store}) => {
const onNewTodo = () => {
store.addTodo(prompt('Enter a new todo:','coffee plz'));
}
return (
{ store.report }
{ store.todos.map(
(todo, idx) =>
) }
{ store.pendingRequests > 0 ? : null }
(double-click a todo to edit)
);
})
ReactDOM.render(
,
document.getElementById('reactjs-app')
);
```
--------------------------------
### Using trace to inspect reactivity
Source: https://mobx.js.org/understanding-reactivity.html
Shows how to use the `trace()` function within a tracked function to inspect MobX's dependency tracking, including output.
```javascript
import { trace } from "mobx"
const disposer = autorun(() => {
console.log(message.title)
trace()
})
// Outputs:
// [mobx.trace] 'Autorun@2' tracing enabled
message.updateTitle("Hello")
// Outputs:
// [mobx.trace] 'Autorun@2' is invalidated due to a change in: 'Message@1.title'
// Hello
```
--------------------------------
### Dereferencing values late - Slower example
Source: https://mobx.js.org/react-optimizations.html
This example shows a less performant way of passing data where the parent component might re-render even if only a deeply nested value changes.
```javascript
```
--------------------------------
### TimerView example demonstrating incorrect observable tracking
Source: https://mobx.js.org/react-integration.html
This example shows a common mistake where observable properties are read outside the `observer` component, preventing reactivity. The `secondsPassed` property is read before being passed to `TimerView`, so `TimerView` does not track changes to it.
```javascript
const TimerView = observer(({ secondsPassed }) => Seconds passed: {secondsPassed})
React.render(, document.body)
```
--------------------------------
### Subclassing Example
Source: https://mobx.js.org/subclassing.html
Demonstrates how to subclass MobX classes, overriding prototype methods and getters using the `override` annotation. It also shows which fields cannot be overridden.
```javascript
import { makeObservable, observable, computed, action, override } from "mobx"
class Parent {
// Annotated instance fields are NOT overridable
observable = 0
arrowAction = () => {}
// Non-annotated instance fields are overridable
overridableArrowAction = action(() => {})
// Annotated prototype methods/getters are overridable
action() {}
actionBound() {}
get computed() {}
constructor(value) {
makeObservable(this, {
observable: observable,
arrowAction: action
action: action,
actionBound: action.bound,
computed: computed,
})
}
}
class Child extends Parent {
/* --- INHERITED --- */
// THROWS - TypeError: Cannot redefine property
// observable = 5
// arrowAction = () = {}
// OK - not annotated
overridableArrowAction = action(() => {})
// OK - prototype
action() {}
actionBound() {}
get computed() {}
/* --- NEW --- */
childObservable = 0;
childArrowAction = () => {}
childAction() {}
childActionBound() {}
get childComputed() {}
constructor(value) {
super()
makeObservable(this, {
// inherited
action: override,
actionBound: override,
computed: override,
// new
childObservable: observable,
childArrowAction: action,
childAction: action,
childActionBound: action.bound,
childComputed: computed,
})
}
}
```
--------------------------------
### TypeScript Configuration
Source: https://mobx.js.org/enabling-decorators.html
Example tsconfig.json to disable experimental decorators.
```json
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": false /* or just remove the flag */
}
}
```
--------------------------------
### makeAutoObservable
Source: https://mobx.js.org/actions.html
Example of using `makeAutoObservable` to automatically infer observable and action properties.
```javascript
import { makeAutoObservable } from "mobx"
class Doubler {
value = 0
constructor() {
makeAutoObservable(this)
}
increment() {
this.value++
this.value++
}
}
```
--------------------------------
### Function props - Usage example
Source: https://mobx.js.org/react-optimizations.html
Shows how to use the GenericNameDisplayer component with different data retrieval functions to render various names efficiently.
```javascript
const MyComponent = ({ person, car }) => (
<>
person.name} />
car.model} />
car.manufacturer.name} />
>
)
```
--------------------------------
### Intercept Example
Source: https://mobx.js.org/intercept-and-observe.html
Demonstrates how to use the `intercept` utility to validate, normalize, and conditionally block changes to an observable property. It also shows how to cancel the interceptor.
```javascript
const theme = observable({
backgroundColor: "#ffffff"
})
const disposer = intercept(theme, "backgroundColor", change => {
if (!change.newValue) {
// Ignore attempts to unset the background color.
return null
}
if (change.newValue.length === 6) {
// Correct missing '#' prefix.
change.newValue = "#" + change.newValue
return change
}
if (change.newValue.length === 7) {
// This must be a properly formatted color code!
return change
}
if (change.newValue.length > 10) {
// Stop intercepting future changes.
disposer()
}
throw new Error("This doesn't look like a color at all: " + change.newValue)
})
```
--------------------------------
### Observer as a Decorator
Source: https://mobx.js.org/enabling-decorators.html
Example of using the 'observer' decorator from 'mobx-react' on a class component.
```typescript
@observer
class Timer extends React.Component {
/* ... */
}
```
--------------------------------
### observable
Source: https://mobx.js.org/observable-state.html
Example demonstrating how to use the 'observable' function to create observable collections like objects with dynamic keys and arrays.
```javascript
import { observable } from "mobx"
const todosById = observable({
"TODO-123": {
title: "find a decent task management system",
done: false
}
})
todosById["TODO-456"] = {
title: "close all tickets older than two weeks",
done: true
}
const tags = observable(["high prio", "medium prio", "low prio"])
tags.push("prio: for fun")
```
--------------------------------
### Transpilation Verification
Source: https://mobx.js.org/installation.html
A piece of code to insert at the beginning of sources to verify correct transpilation settings.
```javascript
if (!new class { x }.hasOwnProperty('x')) throw new Error('Transpiler is not configured correctly');
```