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

В стране морей веб-разработки банда пиратов плыла по виртуальным водам в поисках сокровищ и приключений.

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

1. Установите Redux и начните плавать

  • npm i redux
  • npm i react-redux

2. Создайте глобальный магазин

В трюме корабля пираты хранили все свои сокровища и припасы в массивном государственном объекте, тщательно охраняемом свирепыми пиратами Redux.

  • ⬇️ создать файл магазина src/store.ts
import { createStore } from "redux";
import rootReducer from "./reducers/index";

const store = createStore(rootReducer);
export default store;

3. Создайте редукторы

Под командованием капитана находился опытный квартирмейстер по имени Редьюсер.

Квартирмейстер на пиратском корабле похож на редюсер в приложении React Redux. Так же, как квартирмейстер отвечает за управление припасами и финансами корабля, редьюсер отвечает за управление состоянием и данными в приложении.

Квартирмейстер следит за долей экипажа в добыче и сокровищах и следит за их справедливым распределением. Точно так же редьюсер отслеживает объект состояния и корректно обновляет его в ответ на действия, отправленные компонентом React.

  • 🔽 создать файл корневого редуктора src/reducers/index.ts
import { combineReducers } from "redux";
import pirateValuablesReducer from 'pirateValuablesReducer';

const rootReducer = combineReducers({
  // TODO: combine reducers here
  pirateValuablesReducer
});
export default rootReducer;
  • 🔽 Затем создайте файлы-редюсеры для каждого типа лута и ценностей, которые вы хотите хранить.

Например, вот pirateValuablesReducer

const initialState = {
  gold: 0,
  diamonds: 0,
  pearls: 0,
  treasureMaps: []
};

const pirateValuablesReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_GOLD':
      return {
        ...state,
        gold: state.gold + action.payload
      };
    case 'ADD_DIAMONDS':
      return {
        ...state,
        diamonds: state.diamonds + action.payload
      };
    case 'ADD_PEARLS':
      return {
        ...state,
        pearls: state.pearls + action.payload
      };
    case 'ADD_TREASURE_MAP':
      return {
        ...state,
        treasureMaps: [...state.treasureMaps, action.payload]
      };
    default:
      return state;
  }
};

export default pirateValuablesReducer;

4. Действия

Пираты Redux бороздят просторы открытого моря в поисках сокровищ. Всякий раз, когда пират находит сундук с сокровищами, он отправляет сообщение остальной команде с помощью попугая. В сообщении указывается тип найденного сокровища (например, золото, бриллианты, жемчуг) и количество найденного сокровища.

В этой аналогии попугай — это действие, а сообщение, которое он несет, — это полезная нагрузка. Тип сокровища — это тип действия, а количество сокровищ — полезная нагрузка. Интендант — это восстановитель, и он слушает сообщения от попугая и соответствующим образом обновляет тайник с сокровищами пирата Redux.

export const addGold = (amount) => ({
  type: 'ADD_GOLD',
  payload: amount
});

export const addDiamonds = (amount) => ({
  type: 'ADD_DIAMONDS',
  payload: amount
});

export const addPearls = (amount) => ({
  type: 'ADD_PEARLS',
  payload: amount
});

export const addTreasureMap = (map) => ({
  type: 'ADD_TREASURE_MAP',
  payload: map
});

Каждое действие представляет собой простую функцию, которая возвращает объект действия со свойством type и свойством payload. Свойство type указывает тип действия, а свойство payload указывает значение, которое будет добавлено к соответствующему свойству состояния в редюсере.

5. Компоненты

Компоненты приложения React Redux можно рассматривать как самих пиратов. Как и пираты, компоненты — это те, кто отправляется на поиски сокровищ (то есть данных). Они используют действия, чтобы общаться с остальными членами команды (т. е. редюсерами), когда находят сокровище.

import { useDispatch } from 'react-redux';
import { addGold, addDiamonds, addPearls, addTreasureMap } from './actions';

const MyPirateComponent = () => {
  const dispatch = useDispatch();

  const handleAddGoldClick = () => {
    dispatch(addGold(10));
  };

  const handleAddDiamondsClick = () => {
    dispatch(addDiamonds(5));
  };

  const handleAddPearlsClick = () => {
    dispatch(addPearls(3));
  };

  const handleAddTreasureMapClick = () => {
    dispatch(addTreasureMap({
      location: 'Island X',
      clues: 'Look for the big palm tree with a red X painted on it.'
    }));
  };

  return (
    <div>
      <button onClick={handleAddGoldClick}>Add 10 gold</button>
      <button onClick={handleAddDiamondsClick}>Add 5 diamonds</button>
      <button onClick={handleAddPearlsClick}>Add 3 pearls</button>
      <button onClick={handleAddTreasureMapClick}>Add treasure map</button>
    </div>
  );
};

В этом примере хук useDispatch используется для получения ссылки на функцию отправки, которая затем передается четырем обработчикам событий, которые вызываются при нажатии соответствующей кнопки. Каждый обработчик событий отправляет действие в хранилище с помощью функции отправки.

Например, при нажатии кнопки «Добавить 10 золотых» вызывается обработчик события handleAddGoldClick, который отправляет действие addGold в магазин. Это действие обновляет состояние, добавляя 10 к текущему значению свойства gold в редюсере.

6. Используйте магазин в своем приложении

  • ⬇️ Сделайте магазин доступным для вашего приложения. Измените файл src/index.tsx. Сделайте следующее:
  • import { Provider } from 'react-redux;
  • import store from "./store";
  • Оберните свой компонент <App /> провайдером и отправьте ему импортированный store из файла store.ts.
import { StrictMode } from "react";
import * as ReactDOMClient from "react-dom/client";
import { Provider } from "react-redux"; // Import the provider component.
import store from "./store"; // Import your store here.
import App from "./App";

const rootElement = document.getElementById("root");
const root = ReactDOMClient.createRoot(rootElement);
root.render(
  <StrictMode>
    <Provider store={store}> // <-- Add your provider here
      <App />
    </Provider>
  </StrictMode>
);

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

Спасибо за прочтение. Если вам понравилось, нажмите кнопку «Подписаться»!