47 useState в одном роуте: почему это не проблема управления состоянием

#react#state-management#useState#best-practices

Недавно на аудите одного CRM-подобного дашборда я насчитал 47 вызовов useState в одном роуте. Клиент был уверен, что проблема в управлении состоянием и хотел внедрить Zustand. Но после анализа стало ясно: проблема не в выборе библиотеки, а в том, где и как хранится состояние.

useState как молоток: когда всё выглядит как гвоздь

Когда начинаешь изучать React, useState — это первый инструмент для работы с состоянием. И это здорово, потому что он простой и понятный. Но именно эта простота становится проблемой на практике. Разработчики начинают использовать useState для всего подряд, даже там, где это не нужно.

В моём случае из 47 вызовов только 11 действительно хранили UI-состояние. Остальное было:

И это классическая ошибка: использовать useState для данных, которые не являются состоянием в классическом понимании.

Фильтры, сортировка и страницы: почему это не состояние

Один из ярких примеров — фильтры, сортировка и пагинация. В проекте они хранились в useState. В итоге, если пользователь сортировал таблицу, переходил на третью страницу, а затем возвращался назад, все его действия сбрасывались. Для пользователя это выглядело как баг, хотя технически это была “фича” работы с состоянием.

Решение? Переместить всё в searchParams. Это не только сделало поведение предсказуемым, но и восстановило работу кнопки “Назад” без дополнительных усилий.

Серверные данные в useState: боль и страдания

Ещё один пример — хранение данных с сервера в useState. В проекте это выглядело так:

const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);

useEffect(() => {
  setLoading(true);
  fetch('/api/data')
    .then(response => {
      if (!response.ok) {
        setData(response.body); // Ой!
      } else {
        return response.json();
      }
    })
    .then(data => setData(data))
    .finally(() => setLoading(false));
}, []);

Здесь сразу несколько проблем:

Состояние — это не только useState

Основная мысль, которую я хочу донести: проблема не в том, что useState плохой инструмент. Проблема в том, что его используют не по назначению. Состояние должно быть там, где оно логически принадлежит:

Выводы и рекомендации

Если вы видите десятки useState в одном компоненте, это повод остановиться и подумать:

  1. Анализируйте состояние: что действительно является состоянием, а что можно вычислить или хранить в другом месте?
  2. Используйте правильные инструменты: не всё должно быть в useState.
  3. Тестируйте сценарии использования: как поведёт себя приложение при навигации, обновлении страницы, ошибках?

И помните: архитектура — это не про то, чтобы переместить код из компонента в отдельную папку. Это про то, чтобы правильно распределить ответственность.

А вы сталкивались с похожими ситуациями? Какие правила используете для определения, где должно жить состояние?


Источник: https://www.reddit.com/r/reactjs/comments/1vm69cb/counted_47_usestate_calls_in_one_route_while/