Goodbye, useState

На днях выложили записи докладов с React Miami. Среди спикеров был David Khourshid с докладом о том, когда не стоит использовать useState.

Основная мысль доклада: useState следует использовать только для локального состояния внутри компонента, и только если это состояние влияет на UI. Для всего остального David предлагает следующие альтернативы:

  • Если переменная не участвует в рендере компонента, то вместо useState можно хранить её в useRef;

  • Стейт, отвечающий за выбранные пользователем фильтры (чекбоксы, селекты и т.д.) можно хранить сразу в адресной строке. Так выбранные значения не будут сбрасываться при обновлении страницы. Для этого есть useSearchParams в Next, useSearchParams в react-router или в remix-run/react (что одно и то же). А, ещё есть useQueryState в nuqs.

  • Состояния для обработки асинхронных вызовов (наши любимые isLoading и isError). Во-первых, естественно, вместо них у нас есть RSC или хотя бы useTransition. Ещё для этого есть useQuery из Tanstack Query, которая под капотом работает на useSyncExternalStore. Во-вторых, вместо использования трёх разных состояний для isLoading, isSuccess и isError гораздо удобнее использовать одну переменную с несколькими возможными значениями. Какой-нибудь status: 'success' | 'error' | 'loading'.

  • Состояния для хранения значений инпутов в формах часто дублируют функциональность браузерной FormData API. Но если этого недостаточно, есть Form из remix-run/react, Server Actions в Next, TanStack Form и React Hook Form.

  • Вместо хранения нескольких отдельных стейтов иногда есть смысл объединять их в объект с полями. Например, использовать [user, setUser] вместо отдельных состояний firstName и lastName. Особенно, если таких состояний у вас не два, а штук десять.

  • Вместо того, чтобы сохранять в useState всякие window.innerWidth и отслеживать их изменения через addEventListener в useEffect, можно использовать subscribe из useSyncExternalStore.

  • Не забываем пользоваться useReducer для описывания логики изменения стейта. Главное не пропустить момент, когда вы изобретёте свой собственный Redux.

Что хочется сказать Отличные советы про useRef или про единую переменную с несколькими значениями — они стоят того, чтобы напоминать о них почаще.

Но вообще удивительно, что у нас во фронтенде на каждую задачу найдётся по 10 библиотек. Из всего доклада только в одном из пунктов чувак предложил нативное решение с FormData API.

С таким количеством вендорных решений ни одна нейросеть не успеет научиться нормально код писать))