Коли змінюється значення провайдера контексту, React перерендерює всі компоненти, що читають цей контекст, - навіть якщо вони використовують поле, яке не змінилося. memo на споживачі від цього не захищає.
Пастка 1 - новий об'єкт на кожен рендер провайдера:
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = async (data) => { /* ... */ };
// новий об'єкт і нова функція при КОЖНОМУ рендері AuthProvider
return <AuthContext value={{ user, login }}>{children}</AuthContext>;
}
Будь-який рендер провайдера (наприклад, через стан вище в дереві) змушує всіх споживачів рендеритися. Рішення - стабільне значення:
const login = useCallback(async (data) => { /* ... */ }, []);
const value = useMemo(() => ({ user, login }), [user, login]);
return <AuthContext value={value}>{children}</AuthContext>;
React Compiler робить цю мемоізацію автоматично.
Пастка 2 - один контекст для даних, що змінюються з різною частотою. Тема, користувач і стан кошика в одному контексті: додавання товару перерендерює все, що читає тему.
Рішення - розділити контексти:
<ThemeContext value={theme}>
<UserContext value={user}>
<CartContext value={cart}>{children}</CartContext>
</UserContext>
</ThemeContext>
Розділити стан і дії: компоненти, що лише змінюють стан (кнопка «Додати в кошик»), не мають рендеритися, коли стан змінюється:
<CartStateContext value={items}>
<CartActionsContext value={actions}> {/* стабільний об'єкт, не змінюється */}
{children}
</CartActionsContext>
</CartStateContext>
Коли контексту замало. Контекст - механізм передачі значення, а не сховище з підпискою на частину стану. Для великого стану, що часто змінюється (редактор, складна форма, дані в реальному часі), краще бібліотеки з селекторами - Zustand, Jotai, Redux Toolkit, useSyncExternalStore: компонент підписується лише на потрібне поле й рендериться лише при його зміні.
Що варто пам'ятати: контекст добре підходить для рідко змінюваних даних - тема, мова, поточний користувач, налаштування. Проблеми з продуктивністю зазвичай починаються, коли в контекст кладуть швидко змінюваний стан.