Suggest an editImprove this articleRefine the answer for “Global state and performance”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Global state** is data that can be accessed by **different components from different parts of the application** (the current user, theme, authorization, the cart, etc.), and it is usually stored in the Context API, Redux, Zustand, Jotai, or MobX. **Key point:** keep only the minimum necessary in global state, and keep everything else local, as close as possible to where it is used, because every global state update triggers mass re-renders of all subscribers, even those that don't use the changed field.Shown above the full answer for quick recall.Answer (EN)Image## What "global state" is **Global state** is data that different components from different parts of the application can access, for example: - the current user, - the theme (dark/light), - authorization, - the shopping cart, - application settings, and so on. This data is usually stored in: - the React Context API (`useContext`); - Redux / Zustand / Jotai / MobX; - global store singletons. --- ## The problem: **excessive global state** When a developer starts putting **everything** into a global store, even things needed by **only one component**, a **chain reaction of re-renders and added complexity** appears in the application. --- ## Why this hurts performance ### 1. **Every global state update triggers mass re-renders** By default, React **notifies every consumer of the context (or store)** that reads it, even if it **doesn't use the field that changed**. ```javascript const ThemeContext = createContext(); function App() { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> <Header /> <Main /> <Footer /> </ThemeContext.Provider> ); } ``` If you change `theme`, → **every component using** `useContext(ThemeContext)` gets **re-rendered**, even if it doesn't display the theme directly. The more components are tied to the context, the more unnecessary updates you get. --- ### 2. **State loses its "locality"** If everything is stored in one big store, any update → **triggers subscribers across the whole tree**. For example, changing the "search query" in a product list shouldn't touch the "user profile panel", but if everything is in one Redux slice, both get recomputed. --- ### 3. **You can't memoize effectively** When data is global, it's hard to isolate a component: ```javascript const user = useSelector((state) => state.user); ``` → Any change in `state.user` triggers a re-render in React-Redux, even if the component only uses `user.name`. If there are dozens of such "small" subscriptions, a "cascade of re-renders" begins. --- ### 4. **Contexts don't support partial updates** React Context **does not support diffing by value**. If anything at all changes in the value, every `useContext` consumer gets a new object → **re-render**. ```javascript <Provider value={{ theme, user }}>...</Provider> ``` → even if only `user` changed, a component that uses only `theme` still re-renders, because the object `{ theme, user }` is new by reference. --- ### 5. **Cognitive load grows** The more global state there is, the harder it is to understand: - what is stored where; - who updates it; - which components depend on what. This leads to **unpredictable side effects**, and optimization becomes harder than the business logic itself. --- ### 6. **Problems with concurrent rendering** In React 18, with concurrent mode enabled, React can: - pause a render; - roll back changes; - re-render part of the tree. A large global store makes this **more expensive**, because React is forced to **copy and keep snapshots** of a larger amount of data. --- ## Example (illustrated) ```javascript // everything in a global context - a bad practice const GlobalContext = createContext(); function App() { const [theme, setTheme] = useState('light'); const [cart, setCart] = useState([]); const [search, setSearch] = useState(''); const value = { theme, cart, search, setTheme, setCart, setSearch }; return ( <GlobalContext.Provider value={value}> <Header /> // uses only theme <Search /> // uses only search <Cart /> // uses only cart </GlobalContext.Provider> ); } ``` If you change `search`, - **Header and Cart still re-render**, because `value` (the object) changed by reference. --- ## Solutions (how to do it right) **1. Split your contexts / stores** Create **separate providers** for independent parts: ```javascript <ThemeProvider> <CartProvider> <SearchProvider> <App /> </SearchProvider> </CartProvider> </ThemeProvider> ``` Each context updates in isolation. --- **2. Keep local state local** If the data is only needed by one component (or its children), use `useState` directly in it, rather than in Redux/Context. ```javascript function SearchBar() { const [query, setQuery] = useState(''); ... } ``` --- **3. Use selective subscriptions** If you use Redux / Zustand, use **selectors** and **shallow comparison** to subscribe **only to the fields you need**. ```javascript const price = useSelector(state => state.cart.totalPrice); ``` → It will only change if `totalPrice` changes. --- **4. Use memoization and split components** - Wrap heavy components in `React.memo`; - Pass handlers through `useCallback`; - Split a component so that global data doesn't drag the whole tree along. --- **5. For complex state, use useContextSelector (or Jotai / Zustand)** React 19 will add **Context Selectors** natively. For now you can use `use-context-selector`: it lets you subscribe **to a specific value** in a context instead of the whole object. --- ## Summary | Reason | Why it's harmful | |---|---| | Mass re-renders | All subscribers update even for a small change | | Poor isolation | Any change triggers the whole tree | | Heavy snapshots | Increases memory use and GC work | | Hard to understand dependencies | Increases the chance of bugs | | No targeted optimization possible | Context doesn't diff by field | --- ## The right mindset: > "Keep **only what's necessary** in global state. > Keep everything else **local**, as close as possible to where it's used."For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.