Context - механізм передачі значення вниз по дереву, а не повноцінне керування станом. Його головне обмеження: зміна значення перерендерює всіх споживачів, навіть якщо їм потрібна лише частина даних.
Зовнішній стор тримає стан поза деревом React, а компоненти підписуються на окремі частини через селектори:
// Zustand
const useCartStore = create((set) => ({
items: [],
add: (item) => set((state) => ({ items: [...state.items, item] })),
}));
function CartBadge() {
const count = useCartStore((state) => state.items.length); // лише кількість
return <span>{count}</span>;
}
CartBadge перерендериться лише коли зміниться кількість, а не будь-що в сторі.
// Redux Toolkit
const cartSlice = createSlice({
name: 'cart',
initialState: { items: [] },
reducers: {
added(state, action) {
state.items.push(action.payload); // Immer усередині - виглядає як мутація, але незмінно
},
},
});
Коли зовнішній стор виправданий:
- часті оновлення спільного стану (редактор, канвас, дашборд у реальному часі) - селектори відсікають зайві рендери;
- багато компонентів у різних частинах дерева читають і змінюють той самий стан;
- складна логіка змін, яку зручно тримати поза компонентами й тестувати окремо;
- доступ поза React: з обробників WebSocket, сервісів, роутера;
- інструменти: Redux DevTools (історія дій, «подорож у часі»), збереження стану, middleware.
Коли не потрібен:
- дані з сервера - для них краще TanStack Query чи RTK Query, а не ручне зберігання в сторі;
- стан однієї сторінки чи компонента -
useState/useReducer; - рідко змінювані значення (тема, мова, поточний користувач) - Context цілком достатній.
Порівняння бібліотек:
- Redux Toolkit - структурований, з DevTools і RTK Query, більше коду, але передбачуваний для великих команд;
- Zustand - мінімальний API, хук-стор без провайдера;
- Jotai - атомарний підхід: стан з дрібних незалежних атомів.
Усі вони побудовані на useSyncExternalStore - безпечні для конкурентного рендерингу.
Пастка селекторів: селектор, що повертає новий об'єкт ((s) => ({ a: s.a, b: s.b })), щоразу дає «інше» значення і перерендерює компонент. Потрібні окремі селектори чи порівняння shallow.