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

Как изменить состояние через reducer в Redux?

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

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

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

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

Что такое Redux и Reducer

Redux - это предсказуемое хранилище состояния. Reducer - это чистая функция, которая берет текущее состояние и action, и возвращает новое состояние.

Основной цикл Redux

Action -> Dispatch -> Reducer -> New State -> Components Update

Решение 1: Базовый Redux reducer

export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const SET_NAME = 'SET_NAME';

const initialState = {
  count: 0,
  name: ''
};

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

Решение 2: Redux Toolkit (современный подход)

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

const initialState = {
  count: 0,
  name: '',
  status: 'idle'
};

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

export const { increment, decrement, setName, reset } = counterSlice.actions;
export default counterSlice.reducer;

Решение 3: Использование dispatch в компонентах

import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, setName } from './slices/counterSlice';

export function Counter() {
  const dispatch = useDispatch();
  
  const count = useSelector(state => state.counter.count);
  const name = useSelector(state => state.counter.name);

  return (
    <div>
      <h1>Counter: {count}</h1>
      <p>Name: {name}</p>
      
      <button onClick={() => dispatch(increment())}>
        Increment
      </button>
      
      <button onClick={() => dispatch(decrement())}>
        Decrement
      </button>
      
      <input
        type="text"
        value={name}
        onChange={(e) => dispatch(setName(e.target.value))}
        placeholder="Enter name"
      />
    </div>
  );
}

Решение 4: Асинхронные действия (Thunks)

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

export const fetchUser = createAsyncThunk(
  'user/fetchUser',
  async (userId, { rejectWithValue }) => {
    try {
      const response = await fetch(`/api/users/${userId}`);
      if (!response.ok) throw new Error('Failed');
      return response.json();
    } catch (error) {
      return rejectWithValue(error.message);
    }
  }
);

const userSlice = createSlice({
  name: 'user',
  initialState: { data: null, loading: false, error: null },
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.loading = false;
        state.data = action.payload;
      })
      .addCase(fetchUser.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload;
      });
  }
});

Ключевые принципы

  1. Reducers - чистые функции: нет побочных эффектов
  2. Immutability: не мутируй состояние (Redux Toolkit Immer решает)
  3. Single source of truth: одно глобальное состояние
  4. Actions и Action Creators: явные описания изменений
  5. Dispatch: отправляешь action, redux вызывает reducer
Как изменить состояние через reducer в Redux? | PrepBro