[{"data":1,"prerenderedAt":116},["ShallowReactive",2],{"qa-\u002Freact\u002Frendering-and-performance\u002Fsuspense-concurrent":3},{"page":4,"siblings":96,"blog":113},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":20,"order":21,"path":22,"questions":23,"questionsCount":86,"related":87,"seo":88,"seoDescription":89,"stem":90,"subtopic":91,"topic":92,"topicSlug":93,"updated":94,"__hash__":95},"qa\u002Freact\u002Frendering-and-performance\u002Fsuspense-concurrent.md","Suspense Concurrent",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"hard","md","React","react",{"subtopicSlug":19},"suspense-concurrent",true,5,"\u002Freact\u002Frendering-and-performance\u002Fsuspense-concurrent",[24,29,33,38,42,46,50,54,58,62,66,70,74,78,82],{"id":25,"difficulty":26,"q":27,"a":28},"what-does-suspense-do","easy","What does React Suspense do?","**React Suspense** is a mechanism that lets a component declare that it is\nnot ready to render yet. While the component is suspended, React renders a\n**fallback** UI in its place and picks up where it left off once the\ncomponent is ready.\n\n```jsx\nimport { Suspense, lazy } from 'react'\n\nconst Chart = lazy(() => import('.\u002FChart'))   \u002F\u002F code-split chunk\n\nfunction Dashboard() {\n  return (\n    \u003CSuspense fallback={\u003Cp>Loading chart…\u003C\u002Fp>}>\n      {\u002F* React renders the fallback while Chart's chunk downloads *\u002F}\n      \u003CChart \u002F>\n    \u003C\u002FSuspense>\n  )\n}\n```\n\nSuspense works by catching a special **thrown Promise**. When a component\nthrows a Promise, React walks up the tree looking for the nearest\n`\u003CSuspense>` boundary. That boundary shows its `fallback` until the\nPromise resolves, then re-attempts to render the suspended subtree.\n\nSuspense was originally shipped only for `React.lazy`. In React 18 it was\nextended to data fetching when paired with a **Suspense-compatible**\ndata source (e.g., frameworks that implement the promise-throwing protocol,\nor the new `React.use()` hook).\n\n**Rule of thumb:** Think of `\u003CSuspense>` like an error boundary but for\nloading states — place it wherever you want a loading fallback, not\nnecessarily right above every async component.\n",{"id":30,"difficulty":26,"q":31,"a":32},"suspense-fallback-prop","What is the fallback prop on Suspense and when is it shown?","The **`fallback` prop** accepts any React node and is rendered whenever\nany child inside the `\u003CSuspense>` boundary is currently suspended (i.e.,\nwaiting for a lazy import or a data fetch to complete).\n\n```jsx\n\u003CSuspense fallback={\u003CSpinner size=\"lg\" \u002F>}>\n  \u003CUserProfile userId={id} \u002F>   {\u002F* may suspend while fetching *\u002F}\n\u003C\u002FSuspense>\n```\n\nKey timing rules:\n- The fallback appears **immediately** when a child suspends on the\n  initial render.\n- During a **transition** (`startTransition` \u002F `useTransition`), React\n  keeps showing the previous UI — not the fallback — until the new tree\n  is ready. This avoids unwanted spinners during navigations.\n- If a child suspends **after** the boundary already committed (e.g., a\n  nested update), React shows the fallback again only if the boundary\n  has not already resolved.\n\n`fallback` should be lightweight. A heavy fallback that itself needs data\ndefeats the purpose — keep it a skeleton, spinner, or placeholder.\n\n**Rule of thumb:** One Suspense boundary per independent loading region.\nNesting boundaries gives fine-grained control; a single top-level boundary\ngives a coarser \"page is loading\" experience.\n",{"id":34,"difficulty":35,"q":36,"a":37},"suspense-lazy-vs-data-fetching","medium","What is the difference between using Suspense for lazy loading versus data fetching?","**Lazy loading** (`React.lazy`) uses Suspense to defer the download of a\nJavaScript bundle. It is fully supported in React 16.6+ and works in both\nlegacy and concurrent mode.\n\n**Data fetching** with Suspense requires the data source to implement the\n**throw-a-Promise** protocol, which React 18+ handles reliably in\nconcurrent mode. React itself does not fetch data — frameworks like\nNext.js, Relay, or SWR wire this up for you.\n\n```jsx\n\u002F\u002F 1. Lazy loading — supported everywhere\nconst Modal = lazy(() => import('.\u002FModal'))\n\n\u002F\u002F 2. Data fetching via React.use() — React 18+\nfunction Profile({ userPromise }) {\n  const user = use(userPromise)   \u002F\u002F throws the promise if pending\n  return \u003Ch1>{user.name}\u003C\u002Fh1>\n}\n\n\u002F\u002F Parent wraps both the same way\n\u003CSuspense fallback={\u003CSkeleton \u002F>}>\n  \u003CModal \u002F>          {\u002F* or *\u002F}\n  \u003CProfile userPromise={fetchUser(id)} \u002F>\n\u003C\u002FSuspense>\n```\n\nThe fallback mechanism is identical; the difference is what triggers the\nsuspend: a missing chunk vs. unresolved data.\n\n**Rule of thumb:** Use `React.lazy` for route-level code splitting today;\nuse data Suspense only through a framework or library that supports it —\nhand-rolling the throw-a-Promise protocol is fragile.\n",{"id":39,"difficulty":35,"q":40,"a":41},"suspense-compatible-data-source","What does \"Suspense-compatible\" data source mean?","A **Suspense-compatible** data source is any library or API that signals\n\"not ready yet\" by throwing a Promise when React tries to render a\ncomponent that needs its data. React catches the thrown Promise, shows the\nnearest Suspense fallback, and re-renders the component after the Promise\nresolves.\n\n```js\n\u002F\u002F Simplified read() that implements the protocol\nfunction createResource(promise) {\n  let status = 'pending', result\n  const suspender = promise.then(\n    data  => { status = 'success'; result = data },\n    error => { status = 'error';   result = error }\n  )\n  return {\n    read() {\n      if (status === 'pending')  throw suspender   \u002F\u002F suspend!\n      if (status === 'error')    throw result      \u002F\u002F bubble to error boundary\n      return result                                 \u002F\u002F return data when ready\n    }\n  }\n}\n```\n\nBuilt-in or framework-level Suspense-compatible sources in 2024:\n- `React.lazy` (code splitting)\n- `React.use(promise)` (React 18+)\n- Next.js App Router async Server Components\n- Relay's `useFragment` \u002F `useLazyLoadQuery`\n- SWR and React Query (experimental Suspense mode)\n\n**Rule of thumb:** Never throw a raw Promise from your own components —\nuse `React.use()` or a library. The protocol has subtle caching\nrequirements that are easy to get wrong.\n",{"id":43,"difficulty":35,"q":44,"a":45},"use-transition-explained","What does useTransition do and when should you use it?","**`useTransition`** returns `[isPending, startTransition]`. Wrapping a\nstate update inside `startTransition` tells React that the update is\n**non-urgent**: React can interrupt it, keep the current UI interactive,\nand yield to higher-priority work (e.g., typing) while computing the new\ntree.\n\n```jsx\nimport { useState, useTransition } from 'react'\n\nfunction SearchPage() {\n  const [query, setQuery]     = useState('')\n  const [results, setResults] = useState([])\n  const [isPending, startTransition] = useTransition()\n\n  function handleChange(e) {\n    setQuery(e.target.value)                 \u002F\u002F urgent — update input immediately\n    startTransition(() => {\n      setResults(heavyFilter(e.target.value)) \u002F\u002F non-urgent — can be deferred\n    })\n  }\n\n  return (\n    \u003C>\n      \u003Cinput value={query} onChange={handleChange} \u002F>\n      {isPending && \u003CSpinner \u002F>}\n      \u003CResultList items={results} \u002F>\n    \u003C\u002F>\n  )\n}\n```\n\n`isPending` is `true` while the transition render is in flight, letting\nyou show a subtle loading indicator without hiding the current content.\n\n**Rule of thumb:** Use `useTransition` when a state change triggers an\nexpensive re-render (e.g., filtering a large list, navigating to a heavy\nroute) and you want the UI to stay responsive during it.\n",{"id":47,"difficulty":26,"q":48,"a":49},"start-transition-function","What is startTransition and how does it differ from the useTransition hook?","**`startTransition`** is a standalone function imported directly from\nReact. It marks the state updates inside its callback as non-urgent\ntransitions, identical to the `startTransition` returned by\n`useTransition`.\n\n```jsx\nimport { startTransition } from 'react'\n\n\u002F\u002F Use the standalone import when you don't need isPending\nfunction handleTabChange(tab) {\n  startTransition(() => {\n    setActiveTab(tab)   \u002F\u002F non-urgent — React can interrupt if needed\n  })\n}\n```\n\nThe key difference:\n\n| | `startTransition` (import) | `useTransition` (hook) |\n|---|---|---|\n| Returns `isPending` | No | Yes |\n| Usable outside components | Yes | No (hook rules) |\n| Usable in event handlers | Yes | Yes |\n\nBoth produce the same concurrent behavior — the standalone version is\nsimply for cases where you do not need to reflect the pending state in UI,\nor when you are in a utility function outside a component.\n\n**Rule of thumb:** Prefer `useTransition` inside components so you can\nexpose `isPending` for a loading indicator. Use the standalone\n`startTransition` in router libraries, event utilities, or anywhere hooks\ncannot be called.\n",{"id":51,"difficulty":35,"q":52,"a":53},"use-deferred-value-explained","What does useDeferredValue do?","**`useDeferredValue`** accepts a value and returns a **deferred copy**\nthat lags behind the original during concurrent rendering. React renders\nthe urgent update with the latest value first, then re-renders with the\ndeferred value in the background when the browser is idle.\n\n```jsx\nimport { useState, useDeferredValue } from 'react'\n\nfunction FilteredList({ items }) {\n  const [filter, setFilter] = useState('')\n  const deferredFilter = useDeferredValue(filter)\n  \u002F\u002F deferredFilter may be one or more renders behind `filter`\n\n  const visible = items.filter(i =>\n    i.name.toLowerCase().includes(deferredFilter)\n  )\n\n  return (\n    \u003C>\n      \u003Cinput\n        value={filter}\n        onChange={e => setFilter(e.target.value)}  \u002F\u002F stays snappy\n      \u002F>\n      \u003CList items={visible} \u002F>   {\u002F* re-renders are deferred *\u002F}\n    \u003C\u002F>\n  )\n}\n```\n\nThe component that reads `deferredFilter` renders with the stale value\nwhile the urgent render (updating the input) commits first — the user\nsees no jank.\n\n**Rule of thumb:** Use `useDeferredValue` when you receive a value from a\nprop or context that you cannot control with `startTransition` — it lets\nyou defer a **derived** expensive render without touching where the value\noriginates.\n",{"id":55,"difficulty":14,"q":56,"a":57},"use-transition-vs-use-deferred-value","What is the difference between useTransition and useDeferredValue?","Both APIs defer work so React can keep the UI responsive, but they\noperate at different points in the data flow.\n\n**`useTransition`** wraps the **state setter** — you control which update\nis non-urgent at the source.\n\n**`useDeferredValue`** wraps the **value** downstream — you defer the\nexpensive consumption of a value you didn't produce (e.g., a prop from a\nparent or a context value).\n\n```jsx\n\u002F\u002F useTransition — you own the state setter\nconst [isPending, startTransition] = useTransition()\nstartTransition(() => setItems(newItems))   \u002F\u002F mark update as non-urgent\n\n\u002F\u002F useDeferredValue — someone else sets the state; you defer reading it\nfunction ExpensiveChild({ query }) {         \u002F\u002F query comes from a parent\n  const deferredQuery = useDeferredValue(query)\n  const results = heavySearch(deferredQuery) \u002F\u002F runs behind the scenes\n  return \u003CList items={results} \u002F>\n}\n```\n\n| | `useTransition` | `useDeferredValue` |\n|---|---|---|\n| Controls | the state update | the consumed value |\n| Exposes `isPending` | Yes | No |\n| Use when | you own the setter | the value comes from outside |\n\n**Rule of thumb:** Reach for `useTransition` first — it is more explicit.\nFall back to `useDeferredValue` when the value originates in a parent you\ncannot modify.\n",{"id":59,"difficulty":14,"q":60,"a":61},"tearing-concurrent-rendering","What is \"tearing\" in concurrent rendering and how does React prevent it?","**Tearing** is a visual inconsistency where different parts of the UI\nread the same external store at different points in time during a\nconcurrent render, producing a UI where some components show an old value\nand others show a new value simultaneously.\n\n```js\n\u002F\u002F External mutable store (not React state)\nlet externalColor = 'blue'\n\nfunction A() { return \u003Cdiv style={{ color: externalColor }} \u002F> }\nfunction B() { return \u003Cdiv style={{ color: externalColor }} \u002F> }\n\u002F\u002F If externalColor changes to 'red' mid-render:\n\u002F\u002F A → reads 'blue', B → reads 'red' → tearing\n```\n\nReact prevents tearing for **React-managed state** automatically because\nconcurrent renders compute a snapshot and commit it atomically. However,\n**external stores** (Redux, Zustand, Jotai, custom globals) can still\ntear if they are not integrated correctly.\n\nReact 18 introduced the **`useSyncExternalStore`** hook to fix this. It\nforces the store subscription to produce a synchronous, consistent\nsnapshot that React can safely read without tearing.\n\n```jsx\nimport { useSyncExternalStore } from 'react'\n\nconst color = useSyncExternalStore(\n  store.subscribe,          \u002F\u002F subscribe fn\n  store.getSnapshot,        \u002F\u002F synchronous snapshot\n  store.getServerSnapshot   \u002F\u002F SSR snapshot\n)\n```\n\n**Rule of thumb:** If you integrate a custom external store with\nconcurrent React, always use `useSyncExternalStore` — never read from\na mutable global directly inside a render.\n",{"id":63,"difficulty":35,"q":64,"a":65},"create-root-vs-legacy-render","What is the difference between ReactDOM.createRoot and the legacy ReactDOM.render?","**`ReactDOM.createRoot`** is the React 18 API that enables **concurrent\nmode**. The legacy `ReactDOM.render` runs React in **legacy (blocking)\nmode** where every render is synchronous and cannot be interrupted.\n\n```jsx\n\u002F\u002F Legacy mode — React 17 and below (or React 18 opt-out)\nimport ReactDOM from 'react-dom'\nReactDOM.render(\u003CApp \u002F>, document.getElementById('root'))\n\n\u002F\u002F Concurrent mode — React 18+\nimport { createRoot } from 'react-dom\u002Fclient'\nconst root = createRoot(document.getElementById('root'))\nroot.render(\u003CApp \u002F>)\n```\n\nKey differences:\n\n| | `ReactDOM.render` | `createRoot` |\n|---|---|---|\n| Rendering mode | Synchronous \u002F blocking | Concurrent (interruptible) |\n| `useTransition` works | No | Yes |\n| Automatic batching | Only inside event handlers | All state updates |\n| Suspense for data | Limited | Full |\n\nSwitching to `createRoot` is the single change needed to opt the entire\napp into React 18 concurrent features. Third-party libraries may need\nupdates to be concurrent-safe.\n\n**Rule of thumb:** All new React 18 apps should use `createRoot`. Migrate\nexisting apps by searching for `ReactDOM.render` — it is the single\nswitch that unlocks every concurrent feature.\n",{"id":67,"difficulty":14,"q":68,"a":69},"concurrent-rendering-interruptibility","What does it mean that concurrent rendering is \"interruptible\"?","In **legacy (blocking) mode**, once React starts rendering a tree it runs\nsynchronously to completion — no other JS can run until it finishes. Large\nrenders block the main thread and cause jank.\n\nIn **concurrent mode**, React renders in small chunks and regularly\n**yields** control back to the browser between chunks. If a\nhigher-priority update arrives (e.g., a keypress), React **discards** the\nin-progress lower-priority render, handles the urgent work, and then\n**restarts** the lower-priority render from scratch.\n\n```jsx\n\u002F\u002F React can pause this expensive render mid-way\n\u002F\u002F if the user types into an input while it is running\nstartTransition(() => {\n  setItems(filterLargeDataset(query))  \u002F\u002F low priority\n})\n\n\u002F\u002F Keypress → React interrupts the transition render,\n\u002F\u002F updates the input (high priority), then resumes\u002Frestarts\n\u002F\u002F the filterLargeDataset render\n```\n\nThis is why **render functions must be pure and side-effect free** —\nReact may call them multiple times for the same update. Effects (`useEffect`,\n`useLayoutEffect`) still run only once per committed render.\n\n**Rule of thumb:** Treat concurrent rendering as an implementation detail\n— write pure render functions and put side effects in `useEffect`, and\nReact's scheduler handles the rest.\n",{"id":71,"difficulty":35,"q":72,"a":73},"suspense-boundary-nesting","How does nesting Suspense boundaries work and why would you nest them?","You can nest `\u003CSuspense>` boundaries to give **independent loading states**\nto different regions of the UI. React resolves each boundary\nindependently — an outer boundary does not wait for an inner one to\nfinish before showing its content.\n\n```jsx\n\u003CSuspense fallback={\u003CPageSkeleton \u002F>}>        {\u002F* outer *\u002F}\n  \u003CHeader \u002F>\n\n  \u003CSuspense fallback={\u003CSidebarSkeleton \u002F>}>   {\u002F* inner — resolves independently *\u002F}\n    \u003CSidebar \u002F>\n  \u003C\u002FSuspense>\n\n  \u003CSuspense fallback={\u003CMainSkeleton \u002F>}>      {\u002F* inner *\u002F}\n    \u003CMainContent \u002F>\n  \u003C\u002FSuspense>\n\u003C\u002FSuspense>\n```\n\nReact walks up to the nearest boundary when a component suspends:\n- `\u003CSidebar>` suspending shows `\u003CSidebarSkeleton>` — not `\u003CPageSkeleton>`.\n- If `\u003CMainContent>` suspends before `\u003CSidebar>` has resolved, both inner\n  boundaries independently show their fallbacks.\n- The outer boundary only activates if no inner boundary catches the suspend.\n\nNesting boundaries lets the rest of the page stay visible and interactive\nwhile one slow section loads, improving perceived performance.\n\n**Rule of thumb:** Nest Suspense boundaries at each independently loading\nregion. Avoid a single top-level boundary if some data loads fast —\nit forces the whole page to show a spinner longer than necessary.\n",{"id":75,"difficulty":14,"q":76,"a":77},"nextjs-suspense-streaming","How does Next.js use Suspense for streaming SSR?","Next.js App Router renders **React Server Components** on the server and\nstreams the HTML to the browser in chunks via HTTP streaming (chunked\ntransfer encoding). Each `\u003CSuspense>` boundary in the tree acts as a\n**streaming flush point**.\n\n```jsx\n\u002F\u002F app\u002Fdashboard\u002Fpage.tsx (Next.js App Router)\nimport { Suspense } from 'react'\nimport { UserStats } from '.\u002FUserStats'   \u002F\u002F async Server Component\nimport { RecentOrders } from '.\u002FRecentOrders'\n\nexport default function Dashboard() {\n  return (\n    \u003Cmain>\n      \u003Ch1>Dashboard\u003C\u002Fh1>\n\n      \u003CSuspense fallback={\u003CStatsSkeleton \u002F>}>\n        \u003CUserStats \u002F>       {\u002F* Next.js streams this chunk when ready *\u002F}\n      \u003C\u002FSuspense>\n\n      \u003CSuspense fallback={\u003COrdersSkeleton \u002F>}>\n        \u003CRecentOrders \u002F>    {\u002F* streamed independently *\u002F}\n      \u003C\u002FSuspense>\n    \u003C\u002Fmain>\n  )\n}\n```\n\nThe shell HTML (layout, `\u003Ch1>`, skeletons) is sent immediately. As each\nasync Server Component resolves its `await`, Next.js flushes the rendered\nHTML chunk and a small `\u003Cscript>` that replaces the skeleton via React's\nselective hydration.\n\nThis means **Time to First Byte (TTFB)** is fast and the page is\nprogressively useful rather than blank until all data is ready.\n\n**Rule of thumb:** In Next.js App Router, wrap every slow data-fetching\nServer Component in its own `\u003CSuspense>` boundary with a skeleton fallback\n— the streaming benefit is lost if you have no boundaries.\n",{"id":79,"difficulty":14,"q":80,"a":81},"render-as-you-fetch-pattern","What is the \"render-as-you-fetch\" pattern and how does it differ from \"fetch-on-render\"?","**Fetch-on-render** (the traditional pattern) starts fetching inside\n`useEffect` after the component first renders. The component renders a\nloading state, mounts, fires the effect, data arrives, and the component\nre-renders — a **waterfall**.\n\n**Render-as-you-fetch** kicks off the fetch *before* rendering the\ncomponent — at route load time or in an event handler — and passes the\nin-flight Promise into the component. The component immediately reads\n(and suspends on) that Promise.\n\n```jsx\n\u002F\u002F FETCH-ON-RENDER (waterfall)\nfunction Profile() {\n  const [user, setUser] = useState(null)\n  useEffect(() => { fetchUser(id).then(setUser) }, [id])\n  if (!user) return \u003CSpinner \u002F>\n  return \u003Ch1>{user.name}\u003C\u002Fh1>\n}\n\n\u002F\u002F RENDER-AS-YOU-FETCH (no waterfall)\n\u002F\u002F 1. Start fetch when the user clicks the nav link\nlet userPromise = fetchUser(id)     \u002F\u002F fire immediately\n\n\u002F\u002F 2. Pass the promise to the component\nfunction Profile() {\n  const user = use(userPromise)     \u002F\u002F suspends until resolved\n  return \u003Ch1>{user.name}\u003C\u002Fh1>      \u002F\u002F no loading state needed here\n}\n\n\u002F\u002F 3. Wrap with Suspense in the parent\n\u003CSuspense fallback={\u003CSpinner \u002F>}>\n  \u003CProfile \u002F>\n\u003C\u002FSuspense>\n```\n\nRender-as-you-fetch eliminates the round-trip delay between mount and\nfetch start, and removes the need for manual loading-state bookkeeping.\n\n**Rule of thumb:** Prefer render-as-you-fetch for critical path data.\nFrameworks (Next.js, Remix) implement this automatically — adopt the\npattern manually only when fine-tuning client-side navigation.\n",{"id":83,"difficulty":14,"q":84,"a":85},"react-use-hook","What is the React.use() hook and how does it integrate with Suspense?","**`React.use()`** (stable in React 19, available as experimental in React\n18.3) is a hook that reads the value of a **Promise** or **Context**\ninside a component. When passed a pending Promise it throws it, triggering\nthe nearest Suspense boundary — this is the official, built-in way to\nimplement data Suspense without a library.\n\n```jsx\nimport { use, Suspense } from 'react'\n\nasync function fetchUser(id) {\n  const res = await fetch(`\u002Fapi\u002Fusers\u002F${id}`)\n  return res.json()\n}\n\n\u002F\u002F Start the fetch outside the component (render-as-you-fetch)\nconst userPromise = fetchUser(42)\n\nfunction UserCard() {\n  const user = use(userPromise)   \u002F\u002F suspends if pending, throws if rejected\n  return \u003Cp>{user.name}\u003C\u002Fp>\n}\n\nfunction App() {\n  return (\n    \u003CSuspense fallback={\u003Cp>Loading…\u003C\u002Fp>}>\n      \u003CUserCard \u002F>\n    \u003C\u002FSuspense>\n  )\n}\n```\n\nKey properties of `React.use()`:\n- Can be called **conditionally** (unlike other hooks).\n- Also accepts a **Context** object, replacing `useContext` when you need\n  conditional context reading.\n- A rejected Promise surfaces to the nearest **error boundary**, not\n  Suspense.\n\n**Rule of thumb:** Use `React.use(promise)` as the standard way to\nconsume async data in React 19+ components. For React 18 production apps,\nuse a library (SWR, React Query, Relay) that implements the same protocol\nwith caching.\n",15,null,{"description":11},"React Suspense and concurrent rendering interview questions — Suspense for data fetching, useTransition, useDeferredValue, startTransition, concurrent features, and React 18 rendering model.","react\u002Frendering-and-performance\u002Fsuspense-concurrent","Suspense and Concurrent Rendering","Rendering and Performance","rendering-and-performance","2026-06-24","5FoMC1skNjK9widfvdQ--7FtGg1doJ4c-RwdTDNs7T8",[97,101,104,108,112],{"subtopic":98,"path":99,"order":100},"Virtual DOM and Reconciliation","\u002Freact\u002Frendering-and-performance\u002Fvirtual-dom-reconciliation",1,{"subtopic":102,"path":103,"order":12},"React.memo","\u002Freact\u002Frendering-and-performance\u002Freact-memo",{"subtopic":105,"path":106,"order":107},"useMemo and useCallback Patterns","\u002Freact\u002Frendering-and-performance\u002Fusememo-usecallback-patterns",3,{"subtopic":109,"path":110,"order":111},"Code Splitting and Lazy Loading","\u002Freact\u002Frendering-and-performance\u002Fcode-splitting-lazy",4,{"subtopic":91,"path":22,"order":21},{"path":114,"title":115},"\u002Fblog\u002Freact-suspense-concurrent-guide","React Suspense and Concurrent Rendering — A Complete Guide",1782244101022]