Pull to refresh

Mobx: библиотека глобальных сторов (state manager)

Level of difficultyEasy
Reading time4 min
Views15K

Что такое Mobx?

Mobx — это библиотека, дающая разработчикам инструмент для глобального использования переменных и методов между разными компонентами.

Mobx простая и понятная в использовании библиотека, использующая в своей реализации Context API и, по сравнению с Redux, требующая минимум шаблонного кода для инициализации стора.

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

Зачем использовать глобальные сторы?

Глобальный стор упрощает передачу параметров между компонентами, изменение которых вызывает ререндер активного интерфейса.

Также в сторах удобно хранить общие методы — будь то api‑запросы или парсеры данных — которые используются в разных компонентах, но которые сложно передавать передавать между ними по дереву компонентов.

Наглядно поток передачи параметров между компонентами без и с Mobx показан на слайде:

Из чего состоит Mobx хранилище

Mobx стор состоит из двух частей — самого стора с данными и провайдера этого стора.

Провайдер отвечает за хранение стора между ререндерами и за инкапсуляцию компонентов, которые будут использовать этот стор. Также через компонент провайдера передаются исходные значения для стора. А в файле с провайдером объявляется кастомный хук для получения сохраненного стора в компоненте.

Стор в сущности функция‑генератор, которая возвращает объект. Свойства и методы этого объекта будут доступны во всех компонентах внутри провайдера, и при изменениях этих свойств будет происходить ререндер виртуального DOM.

Файловую архитектуру лучше разграничить так, что после объявления провайдера и стора, файл провайдера изменяться не будет, но из него мы только будем импортировать компонент провайдера и хук возвращающий сохраненный в контексте стор.

Изменяться и дополняться новыми атрибутами, таким образом, будет только объект стора, находящийся в отдельном файле, но помните, что фактически в компоненты из него напрямую ничего импортироваться не будет.

Начало работы

Для того чтобы начать использовать Mobx в react-приложении его нужно установить:

npm i mobx mobx-react-lite

Затем чтобы объявить стор, создадим в корне проекта папку stores, и в ней папку для нового стора - AppStore. В этой папке создадим два файла - для провайдера и для обьекта-стора соответственно. Также можно добавить в папку index.js, чтобы задать импорт провайдера из папки AppStore по дефолту.

Файловая структура стора, таким образом, будет выглядеть так:

/stores

   /AppStore

     AppStoreProvider.jsx

     AppStore.js

     index.js

Объявление провайдера и стора

Давайте обьявим провайдер и стор, в котором будет глобальная переменная test и метод для ее изменения toggleTest:

AppStoreProvider.jsx

import { createContext, useContext } from 'react';
import { observer, useLocalObservable } from 'mobx-react-lite';
import { createAppStore } from './AppStore';

const Context = createContext(null);

export const AppStoreProvider = observer(({ children, ...props }) => {
  const store = useLocalObservable(() => createAppStore(props));
  return <Context.Provider value={store}>{children}</Context.Provider>;
});

export const useAppStore = () => {
  const store = useContext(Context);
  if (!store) throw new Error('Use App store within provider!');
  return store;
};

AppStore.js

export const createAppStore = (props) => {
  return {
    test: props.test || 'Hello world',
    toggleTest: function () {
      this.test = this.test === 'Hi!' ? 'How are you?' : 'Hi!';
    },
   
  };
};

После создания провайдера и стора нужно обернуть компоненты, использующие стор, в провайдер. Это нужно для доступа к объектам хранилища.

Сделать это можно где угодно, главное, чтобы компонент, который будет использовать стор имел на каком то уровне своим предком компонент провайдера. В большинстве приложений лучше оборачивать компоненты в провайдер на уровне корневого компонента приложения:

import React, {} from 'react';
import {AppStoreProvider} from '~store/AppStore'; // index.jsx
import {MyComponent} from './MyComponent';

export const App = () => {
  return (
    <AppStoreProvider>
      <MyComponent />
    </AppStoreProvider>
  );
}

Также, здесь мы можем передать исходные значения для стора:

Затем мы можем использовать стор в компоненте.

Для того, чтобы компонент ререндерился при изменении стора, его самого нужно обернуть в функцию observer из библиотеки mobx‑react‑lite.

Сохраненный стор получают из кастомного хука useAppStore:

import React from 'react';
import {observer} from 'mobx-react-lite';
import {useAppStore} from '~store/AppStore'; // index.jsx

export const MyComponent = observer(() => {
  const appStore = useAppStore();

  return (
    <>
      <h1>{appStore.test}</h1>
      <button onClick={() => appStore.toggleTest()}>Toggle</button>
    </>
  );
});

Локальное хранилище

Также с помощью Mobx можно создать локальное хранилище для отдельного компонента. Доступ к небу будет только у этого компонента. Это удобно, если логику нескольких useState нужно вынести за область компонента. Также в локальное хранилище можно вынести некоторые методы, чтобы разгрузить тело компонента. Для добавления локального хранилища его нужно инициализировать в компоненте:

const localStore = useLocalStore();

И объявить само хранилище в отдельном файле файле:

import { useLocalObservable } from 'mobx-react-lite';

const createLocalStore = (props) => {
  return {
    hello: props.hello || 'Hello world',
    toggleHello: function () {
      this.hello = this.hello !== 'Hi!' ? 'How are you?' : 'Hi!';
    },
   
  };
};

export const useLocalStore = (props = {}) => {
  return useLocalObservable(() => createLocalStore(props));
};

Подведем итог

На примере видно, как просто обьявить mobx стор и вызывать его в компоненте.

Определенно, преимуществом Mobx по сравнентю с Redux является простота - как в обьявлении так и в поддержании сторов. Цепочка вызова в Mobx простая - обьявляете переменную или метод в сторе и достаете ее из хука в компоненте - не нужно иметь дело ни с какими редисерами и мидлварами.

Так что используйте Mobx и избегайте редукса головного мозга :)

Ссылка на документацию:

https://mobx.js.org/react-integration.html

спасибо

Tags:
Hubs:
Total votes 1: ↑1 and ↓0+1
Comments22

Articles