[React MobX] MobX React integration

MobX React integration

While MobX works independently from React, they are most commonly used together. In The gist of MobX you have already seen the most important part of this integration: the observer HoC that you can wrap around a React component.

Installation

1
2
3
4
$ npm install -s mobx-react-lite

# Or
# $ npm install -s mobx-react

Usage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// src/main.js

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 } : { timer: Timer }) => <span>Seconds passed: {timer.secondsPassed}</span>)

ReactDOM.render(<TimerView timer={myTimer} />, document.body)

setInterval(() => {
myTimer.increaseTimer()
}, 1000)

Hint: you can play with the above example yourself on CodeSandbox - https://codesandbox.io/s/minimal-observer-p9ti4?file=/src/index.tsx.


The observer HoC automatically subscribes React components to any observables that are used during rendering. As a result, components will automatically re-render when relevant observables change. It also makes sure that components don’t re-render when there are no relevant changes. So, observables that are accessible by the component, but not actually read, won’t ever cause a re-render.

In practice this makes MobX applications very well optimized out of the box and they typically don’t need any additional code to prevent excessive rendering.

For observer to work, it doesn’t matter how the observables arrive in the component, only that they are read. Reading observables deeply is fine, complex expression like todos[0].author.displayName work out of the box. This makes the subscription mechanism much more precise and efficient compared to other frameworks in which data dependencies have to be declared explicitly or be pre-computed (e.g. selectors).

FAQs

Property ‘timer’ does not exist on type ‘{ children?: ReactNode; }’. TS2339

Declare { timer } : { timer: Timer } type to fix that issue.

1
2
3
4
5
Property 'timer' does not exist on type '{ children?: ReactNode; }'.  TS2339

20 | // A function component wrapped with `observer` will react
21 | // to any future change in an observable it used before.
> 22 | const TimerView = observer(({ timer }) => <span>Seconds passed: {timer.secondsPassed}</span>)
1
2
3
4
// A function component wrapped with `observer` will react
// to any future change in an observable it used before.
- const TimerView = observer(({ timer }) => <span>Seconds passed: {timer.secondsPassed}</span>)
+ const TimerView = observer(({ timer } : { timer: Timer }) => <span>Seconds passed: {timer.secondsPassed}</span>)

Can not find module

Export component to fix that issue.

1
2
3
4
5
6
7
8
- ReactDOM.render(<TimerView timer={myTimer} />, document.body)
+ // ReactDOM.render(<TimerView timer={myTimer} />, document.body)

+ export default function TimerPage() {
+ return (
+ <TimerView timer={myTimer}></TimerView>
+ );
}

References

[1] React integration · MobX - https://mobx.js.org/react-integration.html

[2] README · MobX - https://mobx.js.org/README.html

[3] mobxjs/mobx: Simple, scalable state management. - https://github.com/mobxjs/mobx

[4] React – A JavaScript library for building user interfaces - https://reactjs.org/

[5] State and Lifecycle – React - https://reactjs.org/docs/state-and-lifecycle.html

[6] Higher-Order Components – React - https://reactjs.org/docs/higher-order-components.html