Через что прокидывается контекст в React и как изменение провайдера влияет на ререндер
Что проверяют
Знаете ли вы, что контекст это не хранилище состояния, а способ доставки значения вниз по дереву, и понимаете ли правило, по которому React решает перерисовать потребителей. Вопрос чаще всего задают там, где контекстом заменили менеджер состояния и получили тормоза.
Как отвечать
createContext() возвращает объект контекста. Значение отдаётся провайдером (<Ctx.Provider value={...}>, в React 19 допустимо просто <Ctx value={...}>), читается хуком useContext или use. Компонент находит ближайший провайдер выше по дереву рендера, а не по DOM; если провайдера нет, берётся значение по умолчанию из createContext.
С перерисовкой правило такое: при рендере провайдера React сравнивает новое value со старым через Object.is. Если ссылка другая, перерисовываются все компоненты, которые этот контекст читают, независимо от того, какую его часть они используют.
// новый объект на каждый рендер: потребители перерисуются всегда
<Ctx.Provider value={{ user, setUser }}>
// стабильная ссылка
const value = useMemo(() => ({ user, setUser }), [user]);Чем лечат: useMemo на значение, разделение на несколько контекстов (отдельно редко меняющиеся действия, отдельно часто меняющиеся данные), передача тяжёлого поддерева через children провайдера, чтобы оно не пересоздавалось при его обновлении.
Где спотыкаются
Говорят, что React.memo спасает потребителя от перерисовки по контексту. Не спасает: memo сравнивает пропсы, а подписка на контекст идёт мимо них. Компонент, читающий контекст, перерисуется в любом случае, memo полезен для соседей, которые контекст не читают.
Второе: не различают «провайдер перерисовался» и «значение изменилось». Если родитель обновился, а value остался той же ссылкой, потребители не тронуты, поддерево обновляется обычным путём по пропсам.
Третье: складывают в один контекст всё состояние приложения и удивляются, что ввод в поле формы перерисовывает половину страницы. Селекторов у контекста нет, отдать часть значения по подписке он не умеет, поэтому под часто меняющиеся данные нужен либо узкий отдельный контекст, либо внешний стор.