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

В чем разница между useState и useReducer?

1.8 Middle🔥 211 комментариев
#React#State Management

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

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

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

Разница между useState и useReducer

Назначение и область применения

useState — это базовый хук для управления простым состоянием. Он идеален для небольших и независимых значений. useReducer — это более мощный хук для управления сложным состоянием с несколькими подзначениями или когда новое состояние зависит от предыдущего.

Основные отличия

1. Сложность логики обновления

useState подходит для простых обновлений:

const [count, setCount] = useState(0);
setCount(count + 1);

useReducer подходит для сложной логики:

const initialState = { count: 0, loading: false, error: null };

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      return { ...state, count: state.count + 1 };
    case "DECREMENT":
      return { ...state, count: state.count - 1 };
    case "SET_LOADING":
      return { ...state, loading: true, error: null };
    case "SET_ERROR":
      return { ...state, loading: false, error: action.payload };
    default:
      return state;
  }
}

const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: "INCREMENT" });

2. Управление несколькими значениями

useState требует несколько вызовов для разных значений:

const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [age, setAge] = useState(0);
const [loading, setLoading] = useState(false);

useReducer объединяет всё в одном объекте состояния:

const [state, dispatch] = useReducer(reducer, {
  name: "",
  email: "",
  age: 0,
  loading: false
});

3. Зависимость между значениями

useState может привести к несогласованности:

const [items, setItems] = useState([]);
const [selectedId, setSelectedId] = useState(null);

// Если удалить selectedId из items, может быть несогласованность
function removeItem(id) {
  setItems(items.filter(item => item.id !== id));
  // selectedId может остаться невалидным
}

useReducer гарантирует согласованность:

function reducer(state, action) {
  if (action.type === "REMOVE_ITEM") {
    const newItems = state.items.filter(item => item.id !== action.id);
    return {
      items: newItems,
      selectedId: newItems.some(item => item.id === state.selectedId) 
        ? state.selectedId 
        : null
    };
  }
  return state;
}

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

useState:

  • Булево значение (true/false)
  • Простое число или строка
  • Один счётчик
  • Форма с одним полем
  • Состояния не связаны между собой

useReducer:

  • Форма с несколькими полями
  • Состояние с асинхронными операциями (loading, error, data)
  • Сложная иерархия значений
  • Логика обновления зависит от нескольких факторов
  • Нужна история действий (для отладки или отката)

Производительность

useState создаёт отдельные функции обновления для каждого значения.

useReducer использует одну функцию-диспетчер, что может быть эффективнее при передаче в контекст:

// Плохо: каждый setCount создаст новую функцию
<CountContext.Provider value={{ count, setCount }}>
  <Child />
</CountContext.Provider>

// Хорошо: dispatch остаётся стабильной
<DispatchContext.Provider value={dispatch}>
  <Child />
</DispatchContext.Provider>

Гибридный подход

Часто используют комбинацию:

const [state, dispatch] = useReducer(reducer, initialState);
const [debouncedSearch, setDebouncedSearch] = useState("");

Это позволяет управлять основным состоянием через useReducer, а временными значениями (как поле ввода) через useState.

В чем разница между useState и useReducer? | PrepBro