→ MobX — это инструмент управления состоянием. Это еще один магазин, похожий на Redux.

→ Код менее сложный, но мощный. Есть три терминологии:

1. Состояние — данные, которые управляют приложением. Состояние магазина MobX.

Мы помечаем свойство как наблюдаемое, и MobX достаточно умен, чтобы знать, когда значение состояния обновляется. Зависимый.

2. Действия — любой фрагмент кода, который изменяет состояние.

3. Вывод — все, что выводится из состояния без какого-либо дальнейшего взаимодействия.

Установка плагина MobX для Chrome:

→ Теперь, как и в Redux, у нас есть расширение для Chrome, где мы можем просматривать данные о состоянии хранилища MobX. Мы будем использовать его в нашем проекте ниже.

Что мы создаем?

→ Приложение Todo, которое извлекает данные из магазина MobX вместо состояния React.

→ Мы выполним операцию CRUD с состоянием MobX.

Установка Реакт JS:

ШАГ 1: Давайте установим приложение React, используя следующую команду:

npx create-react-app –template mobx-react-todo

ШАГ 2: Установите mobx и mobx-react-lite

npm install mobx mobx-react-lite

→ Мы создали внутри компонентов две папки. Мы можем сослаться на полный код здесь.

Файл: src/components/Home.js

import React from 'react';

function Home({ store }) {
    return (
        <div className="App">
            <h1>MobX 2</h1>
        </div>
    );
}

export default Home

→ Теперь создаются два пустых файла — About.js и UserStore.js

→ В UserStore мы напишем полный код MobX (это наш магазин)

Браузер:

→ Следующим шагом будет запись в UserStore.js

Файл: src/UserStore.js

import { action, computed, makeObservable, observable, autorun, runInAction } from 'mobx';

// DEFAULT STATE
class UserStore {
    userInfo = {
        id: 'C117',
        name: 'code',
        subject: ['English', 'CS', 'Maths']
    }

    constructor() {
        makeObservable(this, {
            userInfo: observable,
            totalSubject: computed,
            updateUser: action,
            addSubject: action
        });
        autorun(this.logUserDetails);  // WILL RUN AFTER EVERY ACTION INVOKE
        runInAction(this.prefetchData);
    }
 
    // All getters behave as computed i.e. instantly calculate without action
    get totalSubject() {
        return this.userInfo.subject.length;
    }

    logUserDetails = () => {
        console.log(`Subject length: ${this.totalSubject()}`);
    }

    updateUser = (name) => {
        return 'NA';
    }

    addSubject = (data) => {
        return 'NA';
    }


    prefetchData = () => {
        console.log('printing prefetchData...');
    }
}
export default UserStore;

Файл: src/App.js

import './App.css';
import Home from './components/Home';
import UserStore from './UserStore';

function App() {
  const store = new UserStore();
  return (
    <Home store={store} />
  );
}

export default App;

→ Теперь, чтобы использовать хранилище в компоненте, мы будем использовать библиотеку mobx-react-lite.

Файл: src/components/Home.js

import React from 'react';
import { observer } from "mobx-react-lite"

function Home({ store }) {
    return (
        <div className="App">
            <h1>MobX Store</h1>
            <h1>{store.userInfo.name} - {store.userInfo.id}</h1>
        </div>
    );
}

export default observer(Home);

→ Ура, мы получили данные нашего первого магазина, то есть имя и идентификатор userInfo 😀

Порядок, в котором консоли печатают:

1-й — все геттеры в магазине MobX будут печатать

2-й — запускается autorun()

3-й — runInAction запускается

Файл: src/UserStore.js

import { action, computed, makeObservable, observable, autorun, runInAction } from 'mobx';

class UserStore {
    userInfo = {
        id: '113',
        name: 'Happy Learnings',
        subject: ['English', 'CS', 'Maths']
    }

    constructor() {
        makeObservable(this, {
            userInfo: observable,
            totalSubject: computed,
            updateUser: action,
            addSubject: action
        });
        autorun(this.logUserDetails);
        runInAction(this.prefetchData);
    }

    get totalSubject() {
        console.log(`getter`);   // ADDED CONSOLE
        return this.userInfo.subject.length;
    }

    logUserDetails = () => {
        console.log(`Subject length: ${this.totalSubject}`); // ADDED CONSOLE
    }

    updateUser = (name) => {
        return 'NA';
    }

    addSubject = (data) => {
        return 'NA';
    }

    prefetchData = () => {
        console.log('run in action...'); // ADDED CONSOLE
    }
}
export default UserStore;

Браузер:

→ Наблюдаем сначала отпечатки геттеров, затем автозапуск и, наконец, runInAction

Обновление состояния MobX:

→ Давайте создадим кнопку для обновления состояния.

→ Для любого состояния, которое нам нужно обновить, мы должны пройти маршрут действия.

→ Мы создадим кнопку и будем использовать этот метод хранения для обновления состояния.

Файл: src/UserStore.js

import { action, computed, makeObservable, observable, autorun, runInAction } from 'mobx';
class UserStore {
    userInfo = {
        id: '113',
        name: 'Happy Learnings',
        subject: ['English', 'CS', 'Maths']
    }
    // NOTE: MakeObservable, autorun and runInAction are written in constructor
    constructor() {
        makeObservable(this, {
            userInfo: observable,
            totalSubject: computed,
            updateUser: action,      // MOBX SHOULD KNOW - UPDATE STATE
            addSubject: action
        });
        autorun(this.logUserDetails);
        runInAction(this.prefetchData);
    }
    get totalSubject() {
        console.log(`getter`);
        return this.userInfo.subject.length;
    }
    logUserDetails = () => {
        console.log(`Subject length: ${this.totalSubject}`);
    }
    updateUser = (name) => {
        this.userInfo.name = name; // UPDATE STATE CODE
    }
    addSubject = (data) => {
        return 'NA';
    }
    prefetchData = () => {
        console.log('run in action...');
    }
}
export default UserStore;

→ Давайте теперь создадим кнопку внутри компонента Home, чтобы обновить это состояние.

Файл: src/components/Home.js

import React from 'react';
import { observer } from "mobx-react-lite"
function Home({ store }) {
    const changeUser = () => {            // FUNCTION CREATE
        store.updateUser("New data");     // USING STORE METHOD TO UPDATE
    }
    return (
        <div className="App">
            <h1>MobX Store</h1>
            <h1>{store.userInfo.name} - {store.userInfo.id}</h1>
            <button onClick={changeUser}>Update User</button> 
        </div>
    );                            // ABOVE BUTTON CREATED TO UPDATE STATE
}
export default observer(Home);

→ Весь код написан в компоненте Home, важно, что мы передаем магазин из приложения

→ Наблюдаем сверху код Home получает магазин.

Файл: src/App.js

import './App.css';
import Home from './components/Home';
import UserStore from './UserStore';     // FETCHING USER STORE
function App() {
  const store = new UserStore();         // INSTANCE IS PASSED IN HOME
  return (
    <>
      <Home store={store} />             // PASSING STORE to HOME
    </>
  );
}
export default App;

ПРИМЕЧАНИЕ:

В MobX экземпляр Store передается компонентам

Браузер:

→ Мы видим, что имя изменилось.

→ Теперь давайте добавим темы и на главной странице прокрутим темы.

Файл: src/components/Home.js

import React from 'react';
import { observer } from "mobx-react-lite"

function Home({ store }) {
    const changeUser = () => {
        store.updateUser("New data");
    }

    const addSubject = () => {              // ADD SUBJECT METHOD
        store.addSubject('Aeronotics');
    }
    return (
        <div className="App">
            <h1>MobX Store</h1>
            <h1>{store.userInfo.name} - {store.userInfo.id}</h1>
            <button onClick={changeUser}>Update User</button>
            <button onClick={addSubject}>Add Subject</button>
            {   // LOOPING SBJECTS ARRAY PRINING HERE, ADD SUB BUTTON CREATED
                store.userInfo.subject.map((key, index) => <p key={index}>{key}</p>)
            }
        </div>
    );
}

export default observer(Home);

→ В магазине этот метод протолкнет массив

Файл: src/UserStore.js

Примечание. Любая функция, которую мы хотим создать, должна выполняться только в классе Store.

import { action, computed, makeObservable, observable, autorun, runInAction } from 'mobx';

class UserStore {
    userInfo = {
        id: '113',
        name: 'Happy Learnings',
        subject: ['English', 'CS', 'Maths']     // SUBJECT ARRAY
    }

    constructor() {
        makeObservable(this, {
            userInfo: observable,
            totalSubject: computed,
            updateUser: action,
            addSubject: action        // REGISTER IN MOBX
        });
        autorun(this.logUserDetails);
        runInAction(this.prefetchData);
    }

    get totalSubject() {
        console.log(`getter`);
        return this.userInfo.subject.length;
    }

    logUserDetails = () => {
        console.log(`Subject length: ${this.totalSubject}`);
    }

    updateUser = (name) => {
        this.userInfo.name = name;
    }

    addSubject = (data) => {          // METHOD TO PUSH IN SUBJECT ARRAY
        this.userInfo.subject.push(data);
    }

    prefetchData = () => {
        console.log('run in action...');
    }
}
export default UserStore;

→ Теперь мы параллельно проверим хранилище Chrome MobX, чтобы наблюдать за состоянием.

→ Откройте инструмент разработчика в Chrome. Так же, как сеть и консоль, также есть MobX (исходит из расширения Chrome, которое мы установили выше).

→ При нажатии кнопки «Обновить пользователя» вызывается метод updateUser в классе.

→ Мы видим, что MobX обнаружил данные. Мы можем увидеть последнюю стоимость магазина здесь.

→ Теперь давайте нажмем кнопку «Добавить тему» ​​— в настоящее время она жестко закодирована (Aeronotics).

Файл: src/components/Home.js (как мы видели в коде выше)

const addSubject = () => {
        store.addSubject('Aeronotics');
    }

→ Нажмите Добавить тему

→ Мы наблюдаем обнаруженные изменения состояния хранилища MobX. Нажмите на addSubject на MobX

→ Мы видим, что Aeronautics добавляется в массив магазина

→ Это также отображается в браузере, как показано выше.

Примечание: одна интересная вещь:

Мы наблюдаем, что журналы в браузере печатаются, когда вызывается addSubject, а не updateUser для этого.

Файл: src/UserStore.js

import { action, computed, makeObservable, observable, autorun, runInAction } from 'mobx';

class UserStore {
    userInfo = {
        id: '113',
        name: 'Happy Learnings',
        subject: ['English', 'CS', 'Maths']
    }

    constructor() {
        makeObservable(this, {
            userInfo: observable,
            totalSubject: computed,
            updateUser: action,
            addSubject: action
        });
        autorun(this.logUserDetails);
        runInAction(this.prefetchData);
    }

    get totalSubject() {
        console.log(`getter`);
        return this.userInfo.subject.length;
    }

    logUserDetails = () => {
    // Added Name in the Log. SO will this method will also invoke in name change       
      console.log(`Subject length: ${this.totalSubject}, Name: ${this.userInfo.name}`);
    } 

    …
    …
}
export default UserStore;

Переход в один и тот же магазин более чем к одному компоненту:

→ Давайте теперь напишем код в файле About.js

Путь: Путь: src/components/About.js (новый компонент)

import { observer } from "mobx-react-lite";
function About({ store }) {    // RECEIVES STORE FROM APP FILE
    return (
        <div className="App">
            <h1>About - {store.userInfo.name}</h1>
        </div>
    );
}
export default observer(About);

Файл: src/App.js

import './App.css';
import Home from './components/Home';
import About from './components/About';
import UserStore from './UserStore';

function App() {
  const store = new UserStore();
  return (
    <>
      <Home store={store} />
      <About store={store} /> PASSING STORE IN ABOUT COMPONENT
    </>
  );
}

export default App;

Гитхаб:

https://github.com/AmirMustafa/react-mobx-todo/tree/mobx

Видео:

Заключительные мысли:

В этой статье мы реализовали магазин MobX с помощью приложения React.js. MobX — это управление состоянием, как и Redux.

MobX можно использовать с тяжелыми проектами. Сложность написания кода MobX намного меньше по сравнению с магазином Redux, и процесс выполняется быстро.

Спасибо, что дочитали до конца 🙌 . Если вам понравилась эта статья или вы узнали что-то новое, поддержите меня, нажав кнопку Поделиться ниже, чтобы охватить больше людей, и/или подпишитесь на Twitter и подпишитесь на Happy Learnings !! чтобы увидеть некоторые другие советы, статьи и вещи, о которых я узнаю и делюсь там.