← Назад к вопросам

Зачем в Redux организовано деление на экшены, хранилища и др?

2.0 Middle🔥 191 комментариев
#State Management

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Архитектура Redux: разделение на компоненты

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

Основные компоненты Redux

1. Actions (Экшены)

Экшены - это объекты, которые описывают, ЧТО произошло в приложении:

const addTodoAction = {
  type: 'ADD_TODO',
  payload: {
    id: 1,
    text: 'Выучить Redux',
    completed: false
  }
};

Экшены содержат тип (type) и данные (payload). Это делает изменения состояния явными и отслеживаемыми.

2. Reducers (Редьюсеры)

Редьюсеры - это чистые функции, которые берут текущее состояние и экшен, затем возвращают новое состояние:

function todosReducer(state = [], action) {
  switch(action.type) {
    case 'ADD_TODO':
      return [...state, action.payload];
    case 'REMOVE_TODO':
      return state.filter(todo => todo.id !== action.payload);
    default:
      return state;
  }
}

Почему это важно:

  • Чистота функций означает, что один и тот же входной экшен всегда производит одинаковый результат
  • Предсказуемость - можно воспроизвести состояние, просто проиграв последовательность экшенов
  • Тестируемость - легко проверить логику обновления состояния

3. Store (Хранилище)

Стор - это единственный объект, который содержит всё состояние приложения:

import { createStore } from 'redux';

const store = createStore(rootReducer);

console.log(store.getState()); // Получить текущее состояние
store.subscribe(() => {
  console.log('Состояние изменилось');
});

Преимущества:

  • Единый источник истины (Single Source of Truth) - вся логика приложения основана на одном состоянии
  • Легче отлаживать - можно проверить состояние в один момент времени
  • Синхронизация между компонентами - автоматически

4. Selectors (Селекторы)

Селекторы - это функции для выборки конкретной части состояния:

const selectTodos = (state) => state.todos;
const selectCompletedTodos = (state) => 
  state.todos.filter(todo => todo.completed);

Преимущества:

  • Отделение логики доступа к данным от компонентов
  • Мемоизация для оптимизации производительности
  • Легче рефакторить структуру состояния

Зачем это разделение нужно

1. Управление сложностью

Большое приложение имеет сложное состояние. Разделение на экшены, редьюсеры и стор позволяет:

  • Организовать код логически
  • Каждая часть отвечает за одно
  • Легче найти баг

2. Отладка

Redux DevTools позволяет:

// Видеть все отправленные экшены
// Перемотать на любой экшен в истории
// Увидеть, как изменялось состояние
// Проверить любой момент времени

3. Тестируемость

test('ADD_TODO добавляет новый todo', () => {
  const state = [];
  const action = { 
    type: 'ADD_TODO', 
    payload: { id: 1, text: 'Тест' } 
  };
  const newState = todosReducer(state, action);
  expect(newState.length).toBe(1);
  expect(newState[0].text).toBe('Тест');
});

4. Предсказуемость и воспроизводимость

Данный экшен всегда создаст одинаковый результат. Это основа для:

  • Time-travel отладки
  • Записи и воспроизведения пользовательских сессий
  • Синхронизации состояния между клиентом и сервером

Полный пример

import { createStore } from 'redux';

// 1. Reducer
const initialState = { count: 0 };

function counterReducer(state = initialState, action) {
  switch(action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

// 2. Store
const store = createStore(counterReducer);

// 3. Actions
store.dispatch({ type: 'INCREMENT' }); // count = 1
store.dispatch({ type: 'INCREMENT' }); // count = 2
store.dispatch({ type: 'DECREMENT' }); // count = 1

// 4. Get state
console.log(store.getState()); // { count: 1 }

Современная альтернатива: Redux Toolkit

Современный подход упрощает синтаксис:

import { createSlice, configureStore } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; },
    decrement: (state) => { state.value -= 1; }
  }
});

const store = configureStore({
  reducer: counterSlice.reducer
});

store.dispatch(counterSlice.actions.increment());

Итог

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

Зачем в Redux организовано деление на экшены, хранилища и др? | PrepBro