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

Как reducer связан со store?

2.3 Middle🔥 201 комментариев
#JavaScript Core

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

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

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

Как reducer связан со store?

Reducer и Store работают вместе в архитектуре управления состоянием (Redux, Vuex, Pinia и т.д.). Это паттерн для централизованного хранения и управления состоянием приложения.

Что такое Store?

Store — это единственный источник истины (single source of truth), который хранит всё состояние приложения:

interface AppState {
  user: {
    id: string;
    name: string;
    email: string;
  };
  theme: 'light' | 'dark';
  notifications: Notification[];
}

const initialState: AppState = {
  user: null,
  theme: 'light',
  notifications: []
};

// Store хранит это состояние
const store = createStore(initialState);

Что такое Reducer?

Reducer — это чистая функция, которая получает текущее состояние и действие (action), затем возвращает новое состояние:

type Action = 
  | { type: 'SET_USER'; payload: User }
  | { type: 'TOGGLE_THEME' }
  | { type: 'ADD_NOTIFICATION'; payload: Notification };

function reducer(state: AppState, action: Action): AppState {
  switch (action.type) {
    case 'SET_USER':
      return { ...state, user: action.payload };
    
    case 'TOGGLE_THEME':
      return {
        ...state,
        theme: state.theme === 'light' ? 'dark' : 'light'
      };
    
    case 'ADD_NOTIFICATION':
      return {
        ...state,
        notifications: [...state.notifications, action.payload]
      };
    
    default:
      return state;
  }
}

Связь между Reducer и Store

1. Store регистрирует Reducer

Cтор создаётся с reducer функцией. Reducer определяет, как изменяется состояние:

// Redux пример
import { createStore } from 'redux';

const store = createStore(reducer);

2. Reducer получает текущее состояние из Store

// Store содержит состояние
const currentState = store.getState();  // { user: null, theme: 'light', ... }

// Это состояние передаётся reducer
function reducer(state, action) {  // state = currentState
  // ...
}

3. Reducer возвращает новое состояние в Store

// Когда dispatch action, reducer возвращает новое состояние
store.dispatch({ type: 'SET_USER', payload: { id: '123', name: 'John' } });

// Цепочка:
// 1. dispatch отправляет action
// 2. store вызывает reducer(currentState, action)
// 3. reducer возвращает newState
// 4. store обновляет состояние
// 5. подписанные компоненты перерисовываются

Полный цикл работы

// Шаг 1: Создать store с reducer
const store = createStore(reducer);

// Шаг 2: Получить начальное состояние
let state = store.getState();
console.log(state);  // { user: null, theme: 'light', notifications: [] }

// Шаг 3: Dispatch action
store.dispatch({ type: 'SET_USER', payload: { name: 'Alice' } });

// Шаг 4: Reducer обработал action и вернул новое состояние
// Reducer: (state, action) => newState

// Шаг 5: Store обновился
state = store.getState();
console.log(state);  // { user: { name: 'Alice' }, theme: 'light', notifications: [] }

Практический пример в React

import { useReducer } from 'react';

interface State {
  count: number;
  isLoading: boolean;
}

type Action = 
  | { type: 'INCREMENT' }
  | { type: 'DECREMENT' }
  | { type: 'SET_LOADING'; payload: boolean };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    case 'SET_LOADING':
      return { ...state, isLoading: action.payload };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, {
    count: 0,
    isLoading: false
  });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>
        Increment
      </button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>
        Decrement
      </button>
    </div>
  );
}

Redux в React (более сложный пример)

import { createStore } from 'redux';
import { useSelector, useDispatch } from 'react-redux';

// 1. Определить reducer
const userReducer = (state = null, action) => {
  switch (action.type) {
    case 'LOAD_USER':
      return action.payload;
    case 'LOGOUT':
      return null;
    default:
      return state;
  }
};

// 2. Создать store
const store = createStore(userReducer);

// 3. Использовать в компоненте
function UserProfile() {
  const user = useSelector(state => state);  // Получить состояние из store
  const dispatch = useDispatch();  // Функция для отправки actions

  const handleLoadUser = () => {
    dispatch({ type: 'LOAD_USER', payload: { id: '1', name: 'John' } });
  };

  const handleLogout = () => {
    dispatch({ type: 'LOGOUT' });
  };

  return (
    <div>
      {user && <p>{user.name}</p>}
      <button onClick={handleLoadUser}>Load User</button>
      <button onClick={handleLogout}>Logout</button>
    </div>
  );
}

Разница между Store и Reducer

AspectStoreReducer
Что это?Объект, хранящий состояниеФункция, обновляющая состояние
ОбязанностьХранить и предоставлять состояниеОпределить, как изменяется состояние
Вход-Текущее состояние + action
ВыходСостояние (через getState)Новое состояние
МутацияНикогда не мутирует напрямуюЧистая функция, не мутирует
КоличествоОдин store на приложениеМожет быть много reducers

Принципы Reducer (из Redux)

1. Чистая функция

// Плохо - мутирует state
function reducer(state, action) {
  state.user = action.payload;  // МУТАЦИЯ!
  return state;
}

// Хорошо - возвращает новый объект
function reducer(state, action) {
  return { ...state, user: action.payload };
}

2. Никаких побочных эффектов

// Плохо - побочный эффект
function reducer(state, action) {
  if (action.type === 'FETCH_USER') {
    fetch('/api/user').then(/* ... */);  // Побочный эффект!
  }
  return state;
}

// Хорошо - чистая логика
function reducer(state, action) {
  if (action.type === 'LOAD_USER') {
    return { ...state, user: action.payload };
  }
  return state;
}

3. Детерминированность

// Плохо - непредсказуемо
function reducer(state, action) {
  return { ...state, random: Math.random() };
}

// Хорошо - тот же input дает тот же output
function reducer(state, action) {
  return { ...state, count: state.count + 1 };
}

Выводы

Store — это контейнер, который:

  • Хранит состояние приложения
  • Предоставляет методы для доступа к состоянию (getState)
  • Принимает действия через dispatch

Reducer — это функция, которая:

  • Определяет, как состояние изменяется в ответ на actions
  • Всегда возвращает новое состояние
  • Остаётся чистой функцией без побочных эффектов

Вместе они создают предсказуемую и тестируемую систему управления состоянием, которая делает отладку и расширение приложения гораздо проще.

Как reducer связан со store? | PrepBro