Introduction to MobX

Reference documentation

Official documentation: mobx.js.org/getting-sta…

juejin.cn/post/684490…

Mobx-react 5.x migrate to mobx-react 6.x: mobx-react.js.org/recipes-mig…

Key terms translation:

English Chinese
observable That can be viewed
observer The observer

Learn Observables and observers

1. Forget mobx and look at an example

const person = {
    name: 'John'.// Getter method, executed when reading the welcomeTip property
    get welcomeTip() {
        console.log('run get welcomeTip');
        return 'Welcome, ' + this.name
    },
    setName(name) {
        this.name = name
    }
};

const MobXExam = (a)= > {
    return (
        <div>
            <p>{person.welcomeTip}</p>
            <input onBlur={e= > e.target.value && person.setName(e.target.value)} placeholder="change name"/>
            <button type="button" onClick={()= > console.log(person.name)}>log person.name</button>
            <button type="button" onClick={()= > console.log(person.welcomeTip)}>log person.welcomeTip</button>
        </div>)}; export default MobXExam;Copy the code

The interface and operation are as follows:

Conclusion:

The MobXExam component can read and change the Person object;

The DOM in the component is not updated after the person object property is changed;

Transform the example with Observable and Observer

import { observable } from 'mobx';
import { observer } from 'mobx-react-lite';

const person = observable({
    // name...
});

const MobXExam = observer((a)= > {
    // return ...
});

export default MobXExam;
Copy the code

The usage is very simple. An Observable is used to wrap the original object, and an Observer is used to wrap the original component. After refreshing the page, we find that “Welcome, John” in the webpage is automatically updated to “Welcome, Tom” after the person object is changed.

Observable and Observer can only be used together, and the absence of either becomes unresponsive.

3. Add an Observable

const person2 = observable({
    name: 'John'
});

const MobXExam = observer((a)= > {
    return (
        <div>
            {/*other code*/}
            <p>{person2.name}</p>
            <input onBlur={e= > e.target.value && (person2.name = e.target.value)} placeholder="change name"/>
        </div>)});Copy the code

Conclusion: A single observer can observe multiple Observables.

4. Add an Observer component

const person = observable({ name: 'John' });

const PersonName = observer(() => <p>{person.name}</p>);

const MobXExam = observer(() => {
    return (
        <div>
            <PersonName/>
            <p>{person.name}</p>
            <input onBlur={e => e.target.value && (person.name = e.target.value)} placeholder="change name"/>
        </div>
    )
});
Copy the code

Conclusion: Multiple Observers can observe multiple Observables.

Observables are global objects that all components can read. Let’s try creating local observables inside components.

How to use MobX in React Hook components

Create a local observable – useLocalStore

UseLocalStore Hook creates a locally observable store that will remain observable throughout the life of the component.

UseLocalStore is an Observable wrapper. The following two methods work the same

const [person] = useState((a)= > observable({ name: 'John' }));
const person = useLocalStore((a)= > ({ name: 'John' }));
Copy the code

Three observe methods

1. observer HOC

import { useLocalStore, observer } from 'mobx-react-lite';

const MobXExam = observer(() => {
    const person = useLocalStore(() => ({
        name: 'John',
        get welcomeTip() {
            console.log('run get welcomeTip');
            return 'Welcome, ' + this.name
        },
    }));
    return (
        <div>
            <p>{person.name}</p>
            <p>{person.welcomeTip}</p>
            <input onBlur={e => e.target.value && (person.name = e.target.value)} placeholder="change name"/>
        </div>
    )
});

export default MobXExam;
Copy the code

2. Observer component

import { useLocalStore, Observer } from 'mobx-react-lite';

const MobXExam = (a)= > {
    // const person = ...
    return (
        <div>
            <Observer>{() = ><p>{person.name}</p>}</Observer>
            <p>{person.welcomeTip}</p>{/ *<input .* /} < /div>)};Copy the code

3. useObserver hook

import { useLocalStore, useObserver } from 'mobx-react-lite';

export const MobXExam = (a)= > {
    // const person = ...
    return useObserver((a)= >({/*}}));Copy the code

Comparison of three observe methods:

Observer HOC and useObserver hooks rerender the entire component when the data changes;

The Observer Component can render locally.

Old usage of mobx 6.xProvider and inject(Understand can be)

import { Provider, inject, observer } from 'mobx-react';
import { observable } from "mobx";

const PersonName = inject('user')(
    observer(({ user }) = > {
        return (<p>{user.name}</p>); }));function Person() {
    return <PersonName/>;
}

function MobXExam() {
    const person = observable({ name: 'John' });
    const toggleName = (a)= > {
        person.name = person.name === 'John' ? 'Tom' : 'John';
    };
    return (
        <div>
            <Provider user={person}>
                <Person/>
            </Provider>
            <button type="button" onClick={()= > toggleName()}>Change Name</button>
        </div>)}export default MobXExam;
Copy the code

MobXProviderContext

mobx-react@6 Add a Context object. The following example reads the lang property in the common module

import { observer, MobXProviderContext } from 'mobx-react';
import { useContext } from 'react';

function useStores() {
    return useContext(MobXProviderContext);
}

const MobXExam = observer((a)= > {
    const { common } = useStores();
    return (
        <div>
            common.lang: {common.lang}
        </div>)});export default MobXExam;
Copy the code