Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Чому Context не завжди підходить для глобального стану?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**React Context не дорівнює глобальному стору** - він задуманий як механізм передачі даних вниз по дереву без prop drilling, а не як повноцінна система керування станом. **Ключове:** для невеликих глобальних прапорців (тема, мова, поточний користувач) Context чудовий, а для складного бізнес-стану краще підходять Zustand, Jotai, Redux Toolkit або React Query.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Ключова ідея React **Context не дорівнює глобальному стору**, він задуманий як **механізм передачі даних вниз по дереву без prop drilling**, а не як повноцінна система керування станом. --- ## Чому Context не завжди підходить для глобального state ### 1. Кожна зміна value викликає ререндер усіх споживачів Коли ти пишеш: ```javascript <MyContext.Provider value={{ user, theme }}> <App /> </MyContext.Provider> ``` React порівнює `value` **за посиланням**. Якщо воно змінилося -> всі компоненти, що використовують `useContext(MyContext)`, **перемальовуються**, навіть якщо потрібне їм поле не змінилося. При великому дереві це дає каскадні оновлення і лаги. **Приклад:** Змінилося `user.name` -> весь UI, що використовує `theme`, теж ререндериться. --- ### 2. Немає "селекторів" (гранулярних підписок) Контекст не вміє підписувати компонент **тільки на частину даних**. > Якщо у `value` лежить `{ user, theme, cart }`, > то при зміні `cart` оновляться навіть ті, кому потрібен тільки `theme`. Рішення - використовувати сторонні інструменти (`use-context-selector`, Zustand, Jotai), але "чистий" Context цього не дає. --- ### 3. Кожне оновлення проходить через React-рендер Контекст не оптимізований під **часто змінюваний стейт** (наприклад, курсор, таймер, введення тексту). При 60 оновленнях за секунду React просто не встигає. **Context = UI-стан**, а не "реактивний потік". --- ### 4. Немає інструментів, middleware і devtools Context: - не має devtools; - не підтримує time-travel; - не дозволяє зручно логувати зміни, відкочувати state, дебажити бізнес-логіку; - не масштабується при складній архітектурі. --- ### 5. Важко масштабувати при рості застосунку Коли застосунок росте, починаються "милиці": десятки контекстів (`AuthContext`, `CartContext`, `UIContext`, `SettingsContext`...), вкладені дерева `Provider`, заплутані залежності і "Provider hell": ```javascript <AuthProvider> <ThemeProvider> <UIProvider> <CartProvider> <App /> </CartProvider> </UIProvider> </ThemeProvider> </AuthProvider> ``` Важко підтримувати, тестувати і розширювати. --- ### 6. Контекст синхронний і локальний Він не призначений для: - асинхронних запитів (fetch/cache/retry); - синхронізації з сервером; - офлайн-даних; - реактивних підписок (WebSocket, SSE тощо). Для цього краще використовувати **React Query**, **Zustand**, **Redux Toolkit** та інші. --- ## Коли Context все ж ідеальний | Застосування | Чому підходить | |---|---| | Тема (light/dark) | Просте, рідкісне змінення | | Мова інтерфейсу (i18n) | Оновлюється тільки при перемиканні мови | | Поточний користувач | Змінюється тільки при логіні/логауті | | Feature flags, налаштування | Малий обсяг даних, низька частота змін | | Compound components | Контекст використовується як внутрішня шина зв'язку (Tabs, Modal, Dropdown тощо) | --- ## Альтернатива для "реального" глобального state | Завдання | Інструмент | |---|---| | Часто змінюваний стан, бізнес-логіка | **Zustand**, **Jotai**, **Redux Toolkit** | | Асинхронні дані (fetch, кеш) | **TanStack Query (React Query)** | | Реактивні підписки, серверні пуші | **RxJS**, **useSyncExternalStore**, власний стор | | Прості статичні дані | **Context** | --- ## Підсумок | Причина | Чому Context не підходить | |---|---| | Часті оновлення | Всі споживачі ререндеряться | | Немає селекторів | Не можна підписатися тільки на частину даних | | Немає інструментів | Не можна дебажити чи контролювати потік | | Погана масштабованість | Provider hell і складні залежності | | Немає асинхронності | Все синхронно і локально | --- **Висновок:** > Context - це механізм "передачі даних вниз по дереву", > а не "глобальне сховище стану". > > Для невеликих глобальних прапорців - чудово. > Для складного бізнес-стейту - краще Zustand, Jotai, Redux Toolkit або React Query.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.