Ревью: провайдер состояния
Вопрос
Перед тобой код на ревью. Скажи вслух, что здесь не так - по убыванию важности.
Читай вслух, как на ревью: сначала что делает код, потом что сломано.
function AppProvider({ children }) {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');
const [cart, setCart] = useState([]);
return (
<AppContext.Provider value={{ user, setUser, theme, setTheme, cart, setCart }}>
{children}
</AppContext.Provider>
);
}
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
value - новый объект на каждом рендере, перерисовываются все потребители
нужен useMemo по зависимостям
всё состояние в одном контексте: смена корзины перерисовывает потребителей темы
разделить на несколько контекстов по частоте изменения
отделить данные от функций-действий - действия стабильны
memo у потребителей контекста не спасёт
Что могут спросить следом
- Как разделить контекст на данные и действия?
- Когда пора уходить с контекста на внешний стор?
Разбор
Новый объект каждый рендер. Литерал в value создаёт новую ссылку, и React
перерисовывает все компоненты, читающие контекст, - даже если ни одно поле не менялось.
React.memo тут не помогает: подписка на контекст обходит сравнение пропсов.
Один контекст на всё. Даже с useMemo остаётся структурная проблема: добавление товара
в корзину перерисует компонент, которому нужна только тема. Контекст обновляется целиком,
подписаться на поле нельзя.
Правильно - разделить по частоте изменения: ThemeContext, UserContext, CartContext.
И отдельно разнести данные и действия: setUser стабилен между рендерами, значит контекст
действий можно мемоизировать с пустыми зависимостями, и его потребители не будут
перерисовываться никогда.
Если обновления частые и точечные - контекст вообще не тот инструмент, нужен стор с подпиской на срез.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.