Как создать свой собственный простой менеджер состояния для React?

На каких принципах основываются менеджеры состояния в React? <br/> Как создать свой собственный менеджер состояния, чтобы лучше понять основные принципы работы Redux и MobX?
  • 28 ноября 2024 г. 21:33
Ответы на вопрос 2
Создание собственного простого менеджера состояния для React может помочь вам лучше понять принципы работы более сложных библиотек, таких как Redux и MobX. Вот основные шаги и идеи, которые помогут вам создать свой собственный менеджер состояния.

### Основные принципы менеджеров состояния

1. **Централизованное состояние**: Все состояния вашего приложения хранятся в одном месте, что упрощает их управление и отслеживание изменений.

2. **Иммутабельность**: Изменения состояния не производятся "на месте", вместо этого создается новое состояние. Это помогает отследить изменения и оптимизировать повторные рендеры.

3. **Подписки и уведомления**: Компоненты подписываются на изменения состояния. Когда состояние изменяется, подписанные компоненты перерисовываются.

4. **Действия (Actions)**: Изменения состояния происходят через действия, которые описывают, что изменилось в состоянии.

5. **Редюсеры (Reducers)**: Функции, которые принимают текущее состояние и действие и возвращают новое состояние.

### Создание простого менеджера состояния

Вот пример простого менеджера состояния для React:

```javascript
import React, { createContext, useContext, useReducer } from 'react';

// Создаем контекст
const StateContext = createContext();

// Определяем начальное состояние
const initialState = {
  count: 0
};

// Определяем редюсер
const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 };
    case 'decrement':
      return { ...state, count: state.count - 1 };
    default:
      return state;
  }
};

// Создаем провайдер состояния
export const StateProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <StateContext.Provider value={{ state, dispatch }}>
      {children}
    </StateContext.Provider>
  );
};

// Создаем хук для использования состояния
export const useAppState = () => {
  return useContext(StateContext);
};
```

### Использование менеджера состояния в компоненте

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

```javascript
import React from 'react';
import { StateProvider, useAppState } from './StateProvider';

const Counter = () => {
  const { state, dispatch } = useAppState();

  return (
    <div>
      <h1>Count: {state.count}</h1>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
};

const App = () => {
  return (
    <StateProvider>
      <Counter />
    </StateProvider>
  );
};

export default App;
```

### Пояснение работы

1. **Создание контекста**: Мы создаем контекст для хранения состояния и функции для его обновления.

2. **Редюсер**: Редюсер определяет, как состояние будет изменяться в ответ на действия.

3. **Провайдер**: Он использует `useReducer` для управления состоянием и предоставляет его через контекст.

4. **Подписка**: Компонент `Counter` использует хук `useAppState` для доступа к состоянию и функции `dispatch`.

### Заключение

Создав такой простую библиотеку управления состоянием, вы познакомитесь с ключевыми концепциями, которые используются в более сложных решениях, таких как Redux и MobX. Вы также сможете расширить свой менеджер состояния, добавляя дополнительные функции, такие как middleware, асинхронные действия и т. д.
В догонку к комментарию: 
При клике на любую кнопку - используется сигнал, который ты создаёшь один раз, экспортируешь его и можешь использовать где угодно, в любом компоненте. Примерно так эти стейт-менеджеры и работают. Они держат состояние/состояния вне компонентов. А работает это из-за самой природы импортов/экспортов. Если ты экспортируешь, например так: export const obj = { count: 0 }, а затем импортируешь этот obj в другом модуле и увеличиваешь count - то этот count будет увеличен для всех модулей, которые его импортировали, либо будут импортировать.
Похожие вопросы