В каких случаях использовать useState и Redux и почему
Что проверяют
Понимаете ли вы, что состояние бывает разного рода и у каждого своё место, или выбираете между «локально» и «глобально» по привычке. Следом часто спрашивают, где хранить данные с сервера и чем Redux отличается от Context.
Как отвечать
Сильный ответ начинается с классификации состояния:
- локальное UI-состояние: открыт ли модал, значение инпута, активная вкладка. Это
useState, для связанных переходовuseReducer. Если значение нужно соседу, его поднимают к общему родителю; - производное: всё, что вычисляется из props и состояния, не хранится вовсе, а считается при рендере;
- серверное: списки, профиль, всё, что пришло из API. Для него есть TanStack Query или RTK Query с кешем, повторными запросами и инвалидацией. Держать это в Redux вручную с флагами
loadingуже не принято; - редко меняющееся общее: тема, язык, текущий пользователь. Подходит
Context, но для частых обновлений он плох: перерисовываются все потребители; - глобальное клиентское: корзина, черновик многошаговой формы, настройки, которые читают и меняют далёкие друг от друга части приложения. Здесь уместен Redux.
Redux сегодня это Redux Toolkit: configureStore, createSlice, чтение через useSelector. Ручные константы экшенов и switch в редьюсере это стиль, от которого ушли сами авторы Redux, а createStore помечен устаревшим. Плюсы Redux: предсказуемый поток данных, Redux DevTools с историей экшенов, middleware. Минус: церемонии и порог входа, поэтому для небольшого глобального состояния часто берут Zustand.
Где спотыкаются
Кладут в Redux всё подряд, включая значение каждого поля формы. Каждое нажатие клавиши проходит через стор, и код раздувается без пользы.
Показывают старый Redux с connect, mapStateToProps и ручными экшенами. Это сразу выдаёт отсутствие свежей практики.
Предлагают заменить Redux одним большим Context. На часто меняющемся состоянии это ведёт к лишним ререндерам всех потребителей.