JavaRush /Курсы /Модуль 3: React /Что такое useReducer и его отличие от useState — когда ег...

Что такое useReducer и его отличие от useState — когда его использовать

Модуль 3: React
2 уровень , 0 лекция
Открыта

Знакомство с useReducer

Добро пожаловать на новый уровень нашего курса по глубокому изучению React и TypeScript! Сегодня мы начнем знакомство с более сложными способами управления состоянием в React. Если useState — это простая отвертка, то useReducer — это уже швейцарский нож: не всегда понятно, зачем он нужен, но иногда без него никуда. Наша сегодняшняя цель — понять useReducer и его место в React.

useReducer — это хук, который позволяет управлять состоянием компонента, особенно если это состояние становится сложным. Он похож на концепцию редьюсеров из Redux, если вы уже слышали об этом. Если нет, не беспокойтесь, мы сейчас всё разберем.

Проще говоря, useReducer — это инструмент, который позволяет обрабатывать изменения состояния через функции, называемые редьюсерами. Вместо того чтобы напрямую вызывать setState, вы "отправляете действия" (actions), а редьюсер решает, как обновить состояние.

Вот базовый синтаксис:

const [state, dispatch] = useReducer(reducerFunction, initialState);
  • reducerFunction — ваша функция, описывающая, как обновляется состояние.
  • initialState — начальное значение вашего состояния.
  • state — текущее состояние вашего компонента.
  • dispatch — функция, которую вы вызываете для "отправки действий".

Отличие от useState

Представьте, что вы — начальник в офисе. Если у вас один подчиненный (простое состояние), можно просто сказать: "Сделай это!" useState. Но если отдел вырос и теперь у вас целая команда с разными задачами, лучше бы создать систему: задачи (actions) отправляются менеджерам (редьюсерам), которые решают, что делать дальше.

Когда использовать useReducer?

  1. Сложное состояние: если у вас есть несколько полей состояния, которые зависят друг от друга, использование useReducer делает код более читаемым.
  2. Четкая логика обновления: когда бизнес-логика обновления состояния включает несколько шагов или условий.
  3. Масштабирование приложения: если вы планируете, что состояние станет сложнее позже (спойлер: почти всегда).

Пример: представьте, что у вас форма регистрации с несколькими полями. С помощью useReducer мы можем четко описать, как каждое действие (например, ввод текста) обновляет состояние формы.

Применение useReducer для управления сложным состоянием

Пример использования useReducer

Представим, что нам нужно реализовать счетчик с действиями "Увеличить", "Уменьшить" и "Сбросить". Сначала посмотрим, как это делается с помощью useReducer.

import React, { useReducer } from 'react';

// Определим начальное состояние
interface CounterState {
  count: number;
}

const initialState: CounterState = { count: 0 };

// Опишем редьюсер
type CounterAction =
  | { type: 'increment' }
  | { type: 'decrement' }
  | { type: 'reset' };

function reducer(state: CounterState, action: CounterAction): CounterState {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      throw new Error('Неизвестное действие');
  }
}

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Счетчик: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Увеличить</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Уменьшить</button>
      <button onClick={() => dispatch({ type: 'reset' })}>Сбросить</button>
    </div>
  );
};

export default Counter;

Разбор примера

  1. Редьюсер: описывает, как состояние обновляется для каждого действия. Например, при "increment" мы увеличиваем значение на 1.
  2. Типизация: CounterState определяет структуру состояния, а CounterAction — возможные действия.
  3. dispatch: функция, с помощью которой мы отправляем действия.

Почему useReducer лучше для сложного состояния?

Рассмотрим пример формы, где у нас есть имя, email и пароль. Сначала попробуем с useState, а потом с useReducer.

Пример с useState:

const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => setName(e.target.value);
const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value);
const handlePasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => setPassword(e.target.value);

Уже видно, как всё начинает путаться. Что если у нас будет 10 полей? 20? Привет, хаос.

Пример с useReducer:

interface FormState {
  name: string;
  email: string;
  password: string;
}

type FormAction =
  | { type: 'updateField', field: string, value: string }
  | { type: 'reset' };

const initialFormState: FormState = {
  name: '',
  email: '',
  password: ''
};

function formReducer(state: FormState, action: FormAction): FormState {
  switch (action.type) {
    case 'updateField':
      return { ...state, [action.field]: action.value };
    case 'reset':
      return initialFormState;
    default:
      throw new Error('Неизвестное действие');
  }
}

const Form = () => {
  const [state, dispatch] = useReducer(formReducer, initialFormState);

  const handleChange = (field: string) => (e: React.ChangeEvent<HTMLInputElement>) => {
    dispatch({ type: 'updateField', field, value: e.target.value });
  };

  const handleReset = () => {
    dispatch({ type: 'reset' });
  };

  return (
    <form>
      <input type="text" value={state.name} onChange={handleChange('name')} placeholder="Имя" />
      <input type="email" value={state.email} onChange={handleChange('email')} placeholder="Email" />
      <input type="password" value={state.password} onChange={handleChange('password')} placeholder="Пароль" />
      <button type="button" onClick={handleReset}>Сброс</button>
    </form>
  );
};

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

1
Задача
Модуль 3: React, 2 уровень, 0 лекция
Недоступна
Простое управление состоянием с useReducer
Простое управление состоянием с useReducer
1
Задача
Модуль 3: React, 2 уровень, 0 лекция
Недоступна
Управление состоянием формы с useReducer
Управление состоянием формы с useReducer
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ