Performance Expert — Series 2

Preview — 3 of 10 questions

The React Compiler automatically inserts memoization where it can prove doing so is safe. When it encounters code whose safety it can't fully prove statically (like calling an arbitrary function from a prop, whose purity it has no way to verify), what does it do?

javascript
function ProductRow({ product, formatters }) {
  // formatters is an object of functions passed as a prop —
  // the compiler cannot statically prove these functions are pure/stable
  const label = formatters.currency(product.price);
  return <span>{label}</span>;
}
AIt throws a build-time error, refusing to compile any component containing code it can't fully analyze
BIt memoizes anyway, optimistically assuming all prop-derived function calls are pure, and lets a runtime error surface later if that assumption turns out to be wrong
CThe compiler conservatively "bails out" of memoizing that specific piece of code (or, in more severe cases, the whole component) — rather than risk silently-incorrect memoization (e.g., caching a value that should have been recomputed because a supposedly-pure function actually had side effects or non-deterministic output), it simply leaves that part unmemoized, falling back to normal, un-optimized re-computation on every render — correct behavior is prioritized over the performance win in cases of genuine uncertainty
DIt automatically wraps formatters.currency in a runtime purity-checking proxy that verifies determinism on every call

Unlike the interactive DevTools Profiler tab (used for manual, ad-hoc investigation during development), what does wrapping part of the tree in the <Profiler> component with an onRenderCallback actually enable?

javascript
function onRenderCallback(id, phase, actualDuration, baseDuration, startTime, commitTime) {
  if (actualDuration > 16) {
    logSlowRender({ id, phase, actualDuration });
  }
}

function App() {
  return (
    <Profiler id="Dashboard" onRenderCallback={onRenderCallback}>
      <Dashboard />
    </Profiler>
  );
}
A<Profiler> is purely a development-only debugging aid identical to the DevTools tab — it cannot be used in a way that reaches production users at all
B<Profiler> replaces React.memo entirely — wrapping a subtree in it automatically applies the same memoization the compiler/manual React.memo would
C<Profiler> only measures the initial mount of its subtree — it cannot report on subsequent re-renders at all
D<Profiler> lets performance timing be captured programmatically, in code, rather than requiring a human to manually open DevTools and watch a flame graph — this makes it possible to build automated, real-world performance monitoring (e.g., sending slow-render data to an analytics/monitoring service from actual production traffic) rather than being limited to a developer's own local, manual investigation

startTransition-marked updates are described as interruptible. What's the actual underlying mechanism that makes this interruption possible, given JavaScript itself is single-threaded?

javascript
// Conceptually, how React processes a large low-priority update:
// [chunk of work] → check: has 5ms passed / is there pending urgent work? →
//   if yes: pause, let browser handle input/paint/etc → resume later
//   if no: continue with next chunk
AReact breaks the rendering work for a low-priority update into small units (roughly aligned with the Fiber architecture's tree structure), and periodically checks — between processing those units — whether it should yield control back to the browser's main thread (e.g., if a higher-priority update, like direct user input, is now pending, or if enough time has elapsed that the browser needs a chance to paint or handle other pending work); if so, it pauses that render, lets the browser do its own work, and resumes the low-priority render later, right where it left off
BReact spawns genuine parallel threads (via Web Workers) internally for every transition, allowing true simultaneous execution alongside urgent work
CstartTransition schedules its callback using the browser's requestIdleCallback API exclusively, which is available and behaves consistently in all browsers/environments
DInterruption relies on generator functions (function*) — React transpiles every component into a generator so that JavaScript's own yield keyword can pause execution mid-render

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.