Какие проблемы могут возникнуть при использовании контекста в React
Что проверяют
Понимаете ли вы, что контекст это транспорт для проброса значения, а не хранилище состояния, и можете ли объяснить, кто именно перерисуется при его изменении. Обычно вопрос ведёт дальше: «как бы вы это чинили» и «когда вместо контекста нужен стор».
Как отвечать
Начните с механики. При смене значения провайдера перерисовываются все компоненты, которые читают этот контекст через useContext или use, независимо от того, нужна ли им изменившаяся часть. React.memo на самом потребителе не спасает: memo сравнивает пропсы, а контекст приходит мимо них. В React 19 провайдер пишется короче, как <ThemeContext value={...}>, но поведение то же.
Дальше по проблемам:
- новый объект на каждый рендер:
value={{ user, setUser }}создаёт новую ссылку при каждом рендере провайдера и будит всех потребителей. ЛечитсяuseMemoдля значения и стабильными колбэками; - один контекст на всё: часто меняющееся состояние (текст в поле, позиция скролла) в одном контексте с редко меняющимся (тема, локаль) даёт лавину лишних рендеров. Делите на несколько контекстов, отдельно данные и отдельно функции-диспетчеры;
- нет селекторов: контекст не умеет отдавать срез значения. Если нужен один кусок большого объекта, берите внешний стор (Zustand, Redux Toolkit) поверх
useSyncExternalStore; - забытый провайдер: без него подставится значение по умолчанию, и вместо явной ошибки вы получите молча неправильный интерфейс. Дефолт делайте
null, а в своём хуке кидайте исключение; - серверные компоненты: провайдер обязан быть клиентским (
"use client"), из Server Component контекст не читается. То, что известно на сервере, лучше передать пропсами.
Стоит упомянуть React Compiler: он снимает часть ручных useMemo, но рассылку по потребителям не отменяет.
Где спотыкаются
Обещают победить лишние рендеры через React.memo на потребителе. Не работает по причине выше.
Считают контекст заменой Redux. Он решает проброс, а не нормализацию данных, кэш серверных запросов и отладку.
Оптимизируют до замеров. Часто лишний рендер стоит доли миллисекунды, а тормозит тяжёлый дочерний компонент. Сначала профайлер в React DevTools, потом правки.