[{"data":1,"prerenderedAt":123},["ShallowReactive",2],{"qa-\u002Freact\u002Fstate-management\u002Fcontext-vs-redux":3},{"page":4,"siblings":107,"blog":120},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":97,"related":98,"seo":99,"seoDescription":100,"stem":101,"subtopic":102,"topic":103,"topicSlug":104,"updated":105,"__hash__":106},"qa\u002Freact\u002Fstate-management\u002Fcontext-vs-redux.md","Context Vs Redux",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","React","react",{},true,3,"\u002Freact\u002Fstate-management\u002Fcontext-vs-redux",[23,28,32,36,40,44,48,52,57,61,65,69,73,77,81,85,89,93],{"id":24,"difficulty":25,"q":26,"a":27},"context-api-what-is-it","easy","What is the Context API and what is its primary use case?","The **Context API** is React's built-in mechanism for sharing values across\na component tree without passing props through every intermediate layer. You\ncreate a context with `createContext`, wrap a subtree in its `Provider`, and\nany descendant can read the value with `useContext`.\n\n```jsx\nconst ThemeContext = createContext('light')  \u002F\u002F default value\n\nfunction App() {\n  return (\n    \u003CThemeContext.Provider value=\"dark\">\n      \u003CLayout \u002F>                 {\u002F* no prop threading needed *\u002F}\n    \u003C\u002FThemeContext.Provider>\n  )\n}\n\nfunction Button() {\n  const theme = useContext(ThemeContext)  \u002F\u002F reads 'dark' directly\n  return \u003Cbutton className={theme}>Click\u003C\u002Fbutton>\n}\n```\n\nIts primary use case is **ambient, infrequently-updated global data** —\nthe authenticated user, current locale, colour theme, or feature flags.\nThese values are read often but change rarely, so the re-render cost is\nlow.\n\n**Rule of thumb:** Context is a dependency-injection mechanism, not a\nstate manager. Reach for it when you want to avoid prop drilling, not when\nyou need a sophisticated state architecture.\n",{"id":29,"difficulty":25,"q":30,"a":31},"context-vs-redux-mental-model","What is the core mental model difference between Context and Redux?","**Context** is a *transport layer* — it teleports a value from a Provider\nto any consumer without passing props. It owns no opinion about how state\nis structured or updated; you still call `useState`\u002F`useReducer` yourself.\n\n**Redux** is a *state architecture* — a single, centralised store with\nstrict rules: state is read-only, updates happen through serialisable\n**actions**, and **reducers** are pure functions that produce the next\nstate. Middleware, selectors, and DevTools are first-class concepts.\n\n```js\n\u002F\u002F Context — you manage the state, Context just shares it\nconst [user, setUser] = useState(null)\n\u003CUserContext.Provider value={{ user, setUser }}>...\u003C\u002FUserContext.Provider>\n\n\u002F\u002F Redux — the store manages everything; components just dispatch\u002Fselect\ndispatch({ type: 'auth\u002Flogin', payload: { id: 1, name: 'Ada' } })\nconst user = useSelector(state => state.auth.user)\n```\n\nThink of it this way: Context answers \"how do I share state?\" — Redux\nanswers \"how do I manage state?\"\n\n**Rule of thumb:** If you find yourself bolting a reducer, middleware, and\nselector logic onto Context, you've reinvented Redux — just use Redux.\n",{"id":33,"difficulty":14,"q":34,"a":35},"context-re-render-problem","Why does Context cause excessive re-renders and when does it become a problem?","Every component that calls `useContext(MyContext)` re-renders **whenever\nthe Provider's `value` reference changes** — regardless of whether the\nspecific slice of that value the component uses actually changed. React\nhas no built-in selector granularity for Context.\n\n```jsx\nconst AppContext = createContext()\n\nfunction Provider({ children }) {\n  const [user, setUser] = useState(null)\n  const [cart, setCart] = useState([])\n\n  \u002F\u002F New object every render — both user AND cart consumers re-render\n  \u002F\u002F even if only `cart` changed\n  return (\n    \u003CAppContext.Provider value={{ user, setUser, cart, setCart }}>\n      {children}\n    \u003C\u002FAppContext.Provider>\n  )\n}\n\nfunction UserBadge() {\n  const { user } = useContext(AppContext)  \u002F\u002F re-renders on every cart update too\n  return \u003Cspan>{user?.name}\u003C\u002Fspan>\n}\n```\n\nThis becomes a real problem when the context value updates **frequently**\n(e.g. every keystroke, every animation frame, a live-updating cart) and\nmany components are subscribed.\n\n**Rule of thumb:** Context re-render overhead is acceptable for values\nthat change a few times per session; it becomes a bottleneck for values\nthat change multiple times per second or that are consumed by dozens of\ncomponents.\n",{"id":37,"difficulty":25,"q":38,"a":39},"context-good-fit","When is Context sufficient — what kinds of state does it handle well?","Context shines for **infrequently-updated, app-wide ambient data** where\nyou need broad access but not granular subscriptions:\n\n- **Auth user** — set on login\u002Flogout, read in many places, almost never\n  changes during a session.\n- **Theme \u002F colour mode** — toggled once in a while, consumed by many\n  components for styling.\n- **Locale \u002F i18n** — changes only when the user switches language.\n- **Feature flags** — loaded once at startup.\n- **UI preferences** — sidebar collapsed, modal stack.\n\n```jsx\n\u002F\u002F A practical, well-scoped auth context\nconst AuthContext = createContext(null)\n\nexport function AuthProvider({ children }) {\n  const [user, setUser] = useState(null)\n  const login  = useCallback(async (creds) => { \u002F* ... *\u002F }, [])\n  const logout = useCallback(() => setUser(null), [])\n\n  \u002F\u002F Memoised so reference only changes when user changes\n  const value = useMemo(() => ({ user, login, logout }), [user, login, logout])\n  return \u003CAuthContext.Provider value={value}>{children}\u003C\u002FAuthContext.Provider>\n}\n```\n\n**Rule of thumb:** If the value changes less than once per user action,\nContext is probably the right tool.\n",{"id":41,"difficulty":14,"q":42,"a":43},"redux-when-necessary","When does an app outgrow Context and actually need Redux?","Redux earns its keep when several of these conditions are true:\n\n1. **High-frequency updates** — shopping carts, real-time feeds, form\n   state with many interdependent fields.\n2. **Complex async** — sequences of API calls with loading\u002Ferror\u002Fretry\n   states that need to be cancelled, debounced, or coordinated.\n3. **Cross-cutting derived state** — selectors that combine slices from\n   multiple parts of the store.\n4. **Large team** — enforced conventions (action types, reducer\n   boundaries) prevent accidental coupling.\n5. **Audit \u002F replay requirements** — you need a full log of every state\n   change for debugging or analytics.\n\n```js\n\u002F\u002F Redux Toolkit slice — clear action\u002Freducer contract\nconst cartSlice = createSlice({\n  name: 'cart',\n  initialState: { items: [], status: 'idle' },\n  reducers: {\n    addItem:    (state, action) => { state.items.push(action.payload) },\n    removeItem: (state, action) => { state.items = state.items.filter(i => i.id !== action.payload) },\n  },\n})\n```\n\n**Rule of thumb:** If you start adding \"Redux-like\" patterns to Context\n(reducers, action types, middleware), stop and use Redux Toolkit instead.\n",{"id":45,"difficulty":14,"q":46,"a":47},"splitting-contexts","How do you split contexts to reduce unnecessary re-renders?","The key insight is that each `useContext` call subscribes to **one**\ncontext. If you split your monolithic context into smaller, focused\ncontexts, a component that consumes only one will not re-render when\nanother changes.\n\n```jsx\n\u002F\u002F ❌ One big context — UserBadge re-renders on every cart change\n\u003CAppContext.Provider value={{ user, cart }}>\n\n\u002F\u002F ✅ Separate contexts — UserBadge only subscribes to UserContext\nconst UserContext = createContext(null)\nconst CartContext = createContext(null)\n\nfunction Providers({ children }) {\n  const [user] = useState(null)\n  const [cart, setCart] = useState([])\n  return (\n    \u003CUserContext.Provider value={user}>\n      \u003CCartContext.Provider value={{ cart, setCart }}>\n        {children}\n      \u003C\u002FCartContext.Provider>\n    \u003C\u002FUserContext.Provider>\n  )\n}\n\nfunction UserBadge() {\n  const user = useContext(UserContext)  \u002F\u002F never re-renders for cart updates\n  return \u003Cspan>{user?.name}\u003C\u002Fspan>\n}\n```\n\nA good heuristic: each context should have a single reason to change.\nIf you find yourself subscribing to the same context from unrelated\ncomponents, split it.\n\n**Rule of thumb:** One concern per context; keep Providers lean so their\nvalue references are stable.\n",{"id":49,"difficulty":14,"q":50,"a":51},"context-usereducer-pattern","How does Context + useReducer work as a lightweight Redux alternative?","Combining `useReducer` with Context gives you Redux's core pattern —\na single dispatch function, a reducer, and a read-only state view — with\nno external dependency.\n\n```jsx\nconst CounterStateContext   = createContext(null)\nconst CounterDispatchContext = createContext(null)  \u002F\u002F separate so consumers that only dispatch don't re-render on state changes\n\nfunction counterReducer(state, action) {\n  switch (action.type) {\n    case 'increment': return { count: state.count + 1 }\n    case 'decrement': return { count: state.count - 1 }\n    default: throw new Error(`Unknown action: ${action.type}`)\n  }\n}\n\nexport function CounterProvider({ children }) {\n  const [state, dispatch] = useReducer(counterReducer, { count: 0 })\n  return (\n    \u003CCounterStateContext.Provider value={state}>\n      \u003CCounterDispatchContext.Provider value={dispatch}>\n        {children}\n      \u003C\u002FCounterDispatchContext.Provider>\n    \u003C\u002FCounterStateContext.Provider>\n  )\n}\n\n\u002F\u002F Consuming components\nconst { count } = useContext(CounterStateContext)   \u002F\u002F reads state\nconst dispatch  = useContext(CounterDispatchContext) \u002F\u002F stable reference, never re-renders for state changes\n```\n\nThis pattern works well for small-to-medium apps. What it still lacks:\nmiddleware, DevTools, and selector memoisation.\n\n**Rule of thumb:** Context + useReducer is a great choice up to ~5 reducers;\nbeyond that the manual wiring overhead starts to rival Redux Toolkit's setup cost.\n",{"id":53,"difficulty":54,"q":55,"a":56},"redux-middleware","hard","What is Redux middleware and why can't Context replicate it natively?","**Middleware** sits between `dispatch` and the reducer, intercepts every\naction, and can transform, delay, cancel, or trigger side effects before\npassing the action along. The two dominant middleware are `redux-thunk`\n(async action creators) and `redux-saga` (complex async flows with\ngenerators).\n\n```js\n\u002F\u002F redux-thunk: dispatch a function instead of a plain object\nexport const fetchUser = (id) => async (dispatch, getState) => {\n  dispatch({ type: 'users\u002FfetchStart' })\n  try {\n    const user = await api.getUser(id)\n    dispatch({ type: 'users\u002FfetchSuccess', payload: user })\n  } catch (err) {\n    dispatch({ type: 'users\u002FfetchFailure', payload: err.message })\n  }\n}\n\n\u002F\u002F RTK wraps this with createAsyncThunk for zero boilerplate\nexport const fetchUser = createAsyncThunk('users\u002Ffetch', (id) => api.getUser(id))\n```\n\nContext has no equivalent. You can put an async function in a Context\nvalue, but you lose the action-log, DevTools integration, cancellation\ntokens, and the ability to chain\u002Fcancel at the middleware layer. Replicating\nsaga-level coordination (race conditions, debounce, takeLatest) in Context\nrequires re-implementing what middleware already provides.\n\n**Rule of thumb:** The moment you need async sequencing beyond a single\n`async\u002Fawait` call, Redux middleware (or React Query for data fetching)\npays for itself immediately.\n",{"id":58,"difficulty":25,"q":59,"a":60},"redux-devtools","What does Redux DevTools offer and why is it valuable?","**Redux DevTools** is a browser extension (and built-in RTK feature) that\ngives you a full observable record of your application's state history.\nKey features:\n\n- **Action log** — every dispatched action listed in order.\n- **State diff** — exactly what changed in the store for each action.\n- **Time-travel debugging** — jump to any past state by clicking an entry\n  in the log; the UI re-renders as if it's at that point in time.\n- **Action replay** — replay a sequence of actions to reproduce a bug.\n- **Import\u002Fexport state** — share a state snapshot with a team member.\n\n```js\n\u002F\u002F RTK configures DevTools automatically in development\nimport { configureStore } from '@reduxjs\u002Ftoolkit'\n\nconst store = configureStore({\n  reducer: rootReducer,\n  \u002F\u002F devTools: true by default in dev, false in production\n})\n```\n\nContext has no equivalent. A console.log in a reducer or a React DevTools\ncomponent inspection is the closest you can get, but neither gives you\ntime-travel or serialisable action history.\n\n**Rule of thumb:** If you've ever said \"I wish I could rewind to see what\ncaused this bug,\" that's the DevTools use case — and it's only available\nwith Redux.\n",{"id":62,"difficulty":14,"q":63,"a":64},"boilerplate-context-vs-rtk","How does the boilerplate of Context compare to Redux Toolkit?","Modern **Redux Toolkit (RTK)** has dramatically closed the boilerplate gap.\nCreating a slice, wiring a store, and connecting a component now requires\nfewer files than a well-structured Context setup.\n\n```js\n\u002F\u002F RTK: one createSlice call replaces action types + action creators + reducer\nconst counterSlice = createSlice({\n  name: 'counter',\n  initialState: { value: 0 },\n  reducers: {\n    increment: state => { state.value += 1 },  \u002F\u002F Immer under the hood — mutate safely\n    decrement: state => { state.value -= 1 },\n  },\n})\n\nexport const { increment, decrement } = counterSlice.actions\nexport default counterSlice.reducer\n```\n\n```jsx\n\u002F\u002F Context equivalent needs: createContext, Provider component,\n\u002F\u002F useState or useReducer, custom hooks, and manual memoisation —\n\u002F\u002F often spread across 3–4 files for a non-trivial piece of state.\n```\n\nThe honest comparison in 2024: RTK setup is ~20 lines; a well-structured\nContext + useReducer setup for the same feature is similar or larger.\nThe Redux tax is now mostly in learning the mental model, not in line count.\n\n**Rule of thumb:** Don't avoid Redux for boilerplate reasons; the RTK API\nis concise. Avoid it because your state needs are genuinely simple.\n",{"id":66,"difficulty":14,"q":67,"a":68},"usememo-context-value","How does useMemo help with Context performance and when is it required?","Every time a Provider's parent re-renders, its `value` prop is a new\nobject literal — which triggers re-renders in all consumers even if the\ndata is identical. **`useMemo`** stabilises the reference so consumers\nonly re-render when the underlying data actually changes.\n\n```jsx\nfunction UserProvider({ children }) {\n  const [user, setUser]   = useState(null)\n  const [token, setToken] = useState(null)\n\n  \u002F\u002F ❌ New object every render, even if user\u002Ftoken haven't changed\n  \u002F\u002F return \u003CCtx.Provider value={{ user, setUser, token, setToken }}>\n\n  \u002F\u002F ✅ Stable reference — consumers re-render only when user or token changes\n  const value = useMemo(\n    () => ({ user, setUser, token, setToken }),\n    [user, token]  \u002F\u002F setUser\u002FsetToken are stable (from useState)\n  )\n\n  return \u003CUserContext.Provider value={value}>{children}\u003C\u002FUserContext.Provider>\n}\n```\n\nWhen is it required? Whenever the Provider's parent can re-render for\nreasons unrelated to the context value — e.g., it lives at the top of the\ntree where any ancestor state change would cascade down.\n\n**Rule of thumb:** Always wrap a Context value object in `useMemo` if\nthe Provider is not at the very root of the tree; skip it only when\nthe Provider is a static singleton that never re-renders.\n",{"id":70,"difficulty":54,"q":71,"a":72},"context-no-selector-granularity","What is the \"no selector granularity\" limitation of Context?","When you call `useContext(MyContext)`, you subscribe to the **entire\ncontext value**. There is no built-in way to say \"re-render only if\n`state.count` changed\" — you always get the whole object, and any change\nto any part of it triggers a re-render.\n\n```jsx\n\u002F\u002F With Redux + useSelector — granular subscription\nconst count = useSelector(state => state.counter.count)\n\u002F\u002F Only re-renders when state.counter.count changes\n\n\u002F\u002F With Context — no selector, full value\nconst { count, user, cart, theme } = useContext(AppContext)\n\u002F\u002F Re-renders whenever ANY of these change\n```\n\nRedux's `useSelector` uses **strict equality** (or a custom comparator)\non the selector's return value. If `state.counter.count` hasn't changed,\nthe component skips re-rendering even if other parts of the store did.\nLibraries like `use-context-selector` backport this behaviour to Context,\nbut at that point you're carrying the complexity of Redux without its\necosystem.\n\n**Rule of thumb:** If you need subscription granularity finer than \"the\nwhole context value\", Redux (or Zustand\u002FJotai) is the right tool.\n",{"id":74,"difficulty":14,"q":75,"a":76},"zustand-jotai-middle-ground","Where do Zustand and Jotai fit between Context and Redux?","**Zustand** and **Jotai** occupy the pragmatic middle ground: they provide\ngranular subscriptions and minimal boilerplate without Redux's architectural\noverhead.\n\n**Zustand** is a single-store solution. You define state and actions together\nin a `create` call; components subscribe to slices with a selector:\n\n```js\nimport { create } from 'zustand'\n\nconst useStore = create(set => ({\n  count: 0,\n  increment: () => set(state => ({ count: state.count + 1 })),\n}))\n\nfunction Counter() {\n  const count     = useStore(state => state.count)      \u002F\u002F granular — re-renders only when count changes\n  const increment = useStore(state => state.increment)  \u002F\u002F stable reference\n  return \u003Cbutton onClick={increment}>{count}\u003C\u002Fbutton>\n}\n```\n\n**Jotai** uses an **atomic** model: each `atom` is an independent piece of\nstate. Components subscribe to individual atoms, so updates are naturally\nscoped to only the atoms a component reads.\n\nNeither has Redux DevTools baked in (though Zustand has a devtools\nmiddleware) or first-class saga\u002Fthunk support.\n\n**Rule of thumb:** Reach for Zustand when Context starts hurting and Redux\nfeels like overkill; reach for Jotai when you want fine-grained atomic\nstate without a centralised store.\n",{"id":78,"difficulty":14,"q":79,"a":80},"testing-context-vs-redux","How does testing differ between Context-based state and Redux?","**Context** — wrap the component under test in its Provider and pass a\ncontrolled value. No special setup, no mock store.\n\n```jsx\n\u002F\u002F Testing a component that reads from Context\ntest('shows user name', () => {\n  render(\n    \u003CUserContext.Provider value={{ user: { name: 'Ada' } }}>\n      \u003CUserBadge \u002F>\n    \u003C\u002FUserContext.Provider>\n  )\n  expect(screen.getByText('Ada')).toBeInTheDocument()\n})\n```\n\n**Redux** — use RTK's `configureStore` with a real (or pre-populated) store,\nor use `renderWithProviders` from `@reduxjs\u002Ftoolkit\u002Freact`:\n\n```jsx\ntest('increments counter', async () => {\n  const { store } = renderWithProviders(\u003CCounter \u002F>)\n  await userEvent.click(screen.getByRole('button', { name: \u002Fincrement\u002Fi }))\n  expect(store.getState().counter.value).toBe(1)\n})\n```\n\nRedux gives you direct access to `store.getState()` and `store.dispatch()`\nin tests, making it easy to assert against the store as well as the UI.\nContext is simpler to mock but harder to inspect state independently of\nthe rendered output.\n\n**Rule of thumb:** Context tests are simpler to write; Redux tests are more\npowerful for asserting state transitions independently from rendering.\n",{"id":82,"difficulty":14,"q":83,"a":84},"multiple-contexts-vs-one-store","How do multiple small contexts compare to one large Redux store?","**Multiple contexts** let you co-locate state near the component subtrees\nthat use it. Each context has an independent update cycle, so they don't\ninterfere with each other. The cost is coordination: sharing data across\ncontexts requires lifting it to a common ancestor, which can recreate\nprop-drilling at the context level.\n\n```jsx\n\u002F\u002F Fine — independent, non-overlapping concerns\n\u003CAuthContext.Provider value={auth}>\n  \u003CThemeContext.Provider value={theme}>\n    \u003CNotificationsContext.Provider value={notifications}>\n      \u003CApp \u002F>\n    \u003C\u002FNotificationsContext.Provider>\n  \u003C\u002FThemeContext.Provider>\n\u003C\u002FAuthContext.Provider>\n```\n\n**One Redux store** centralises everything. Any slice can read from any\nother slice in a selector. The downside is that everything is global by\ndefault — there's no encapsulation boundary.\n\nRTK's `createSlice` recovers some modularity (each slice is a self-contained\nmodule), but ultimately they all merge into one global state tree.\n\n**Rule of thumb:** Multiple contexts for independent concerns; a Redux store\nwhen slices need to derive state from each other or share middleware.\n",{"id":86,"difficulty":25,"q":87,"a":88},"global-vs-local-state","How should you decide between global state (Context\u002FRedux) and local component state?","A useful mental checklist — before reaching for a global state solution,\nask these questions:\n\n```\nDoes only ONE component need this state?     → useState, keep it local\nDo a FEW co-located components need it?      → lift state to nearest common ancestor\nDo MANY unrelated components need it?        → Context (if infrequent updates)\nIs it updated FREQUENTLY or needs middleware? → Redux \u002F Zustand\nIs it SERVER state (loading, caching)?        → React Query \u002F SWR\n```\n\nOver-globalising state is a common mistake: putting form field values,\nmodal-open flags, and tooltip visibility into Redux adds noise to the\naction log and couples unrelated parts of the app. These are **ephemeral\nUI state** — local `useState` is almost always the right choice.\n\n**Rule of thumb:** Default to local state; promote to global only when\nsharing across unrelated subtrees becomes genuinely painful.\n",{"id":90,"difficulty":54,"q":91,"a":92},"context-ssr-nextjs-gotchas","What are the Context gotchas in SSR \u002F Next.js?","In a **Server Component** world (Next.js App Router), Context Providers\nmust be **Client Components** — they rely on React's runtime reconciler,\nwhich only runs in the browser. Trying to render a Context Provider in a\nServer Component throws an error.\n\n```jsx\n\u002F\u002F app\u002Fproviders.tsx — must be a Client Component\n'use client'\nimport { ThemeContext } from '.\u002FThemeContext'\n\nexport function Providers({ children }: { children: React.ReactNode }) {\n  const [theme, setTheme] = useState('dark')\n  return (\n    \u003CThemeContext.Provider value={{ theme, setTheme }}>\n      {children}\n    \u003C\u002FThemeContext.Provider>\n  )\n}\n\n\u002F\u002F app\u002Flayout.tsx — Server Component that wraps with Providers\nimport { Providers } from '.\u002Fproviders'\nexport default function RootLayout({ children }) {\n  return \u003Chtml>\u003Cbody>\u003CProviders>{children}\u003C\u002FProviders>\u003C\u002Fbody>\u003C\u002Fhtml>\n}\n```\n\nAdditional gotchas:\n- **Hydration mismatch** — if Context initialises from browser-only APIs\n  (localStorage, cookies), the server-rendered HTML will differ from the\n  client hydration pass, causing warnings.\n- **Per-request isolation** — in traditional SSR, a singleton Context\n  module is shared across requests. Each request must create its own\n  Provider instance; never store per-user data in a module-level variable.\n\n**Rule of thumb:** In Next.js App Router, keep Providers in a single\n`'use client'` file at the root layout and pass server-fetched data in\nas props rather than initialising them from async operations inside the\nProvider.\n",{"id":94,"difficulty":25,"q":95,"a":96},"context-vs-redux-summary","How do you summarise the choice between Context and Redux for an interviewer?","A strong interview answer covers three axes: **frequency of updates**,\n**complexity of async logic**, and **team\u002Fscale requirements**.\n\n```\nContext is right when:\n  ✓ State changes infrequently (theme, auth, locale)\n  ✓ No async middleware needed\n  ✓ Small-to-medium app or isolated subtree\n  ✓ You want zero extra dependencies\n\nRedux (RTK) is right when:\n  ✓ State updates frequently or drives complex UI\n  ✓ Async sequences: loading\u002Ferror states, cancellation, polling\n  ✓ Derived data across multiple slices (selectors)\n  ✓ Large team needs enforced conventions\n  ✓ Time-travel debugging has real value\n\nMiddle ground (Zustand\u002FJotai):\n  ✓ Granular subscriptions without Redux boilerplate\n  ✓ Stores need to be shared but you don't want a full Redux setup\n```\n\nInterviewers want to hear that you understand the trade-offs, not just\n\"Context is simpler.\" Mention re-render behaviour, selector granularity,\nand middleware — those are the differentiators that signal real experience.\n\n**Rule of thumb:** Start with local state, promote to Context for ambient\nglobal data, reach for Redux when your state has behaviour (async, derived\ndata, audit trail) that Context can't model cleanly.\n",18,null,{"description":11},"Context vs Redux interview questions — when to use each, performance trade-offs, re-render behavior, middleware, devtools, and scaling considerations.","react\u002Fstate-management\u002Fcontext-vs-redux","Context vs Redux","State Management","state-management","2026-06-24","Z9H1j547sQNnxtFWfskeekVWpzfniphJMcA-f2UPPIA",[108,112,115,116],{"subtopic":109,"path":110,"order":111},"Redux Toolkit","\u002Freact\u002Fstate-management\u002Fredux-toolkit",1,{"subtopic":113,"path":114,"order":12},"Zustand","\u002Freact\u002Fstate-management\u002Fzustand",{"subtopic":102,"path":21,"order":20},{"subtopic":117,"path":118,"order":119},"Async State & React Query","\u002Freact\u002Fstate-management\u002Fasync-state-react-query",4,{"path":121,"title":122},"\u002Fblog\u002Freact-context-vs-redux-guide","React Context vs Redux — Complete Interview Guide",1782244101119]