Memoization — Series 2

Preview — 3 of 10 questions

The Profilers flame graph shows `ExpensiveChart` taking 1.6ms of `Dashboard`s 1.8ms total. What does this actually tell you about where to focus optimization effort?

javascript
// After recording a profiling session in React DevTools' Profiler tab,
// a commit shows: App (2ms) → Dashboard (1.8ms) → ExpensiveChart (1.6ms) → StatCard × 20 (0.01ms each)
AApp is the real bottleneck, since it's the topmost/outermost bar and always accumulates the most total time by definition
BThe 20 StatCard instances are the priority, since there are more of them than any other component in this render
CExpensiveChart accounts for the large majority of this commit's render time (1.6ms of 1.8ms) — it's the component actually worth investigating/optimizing first; the many cheap StatCards (0.01ms each) are, despite their count, not where the time is going, and optimizing them would yield negligible improvement to this commit's total time
DThe flame graph only shows which components rendered, not how long each one took — timing information requires a separate browser performance profiler

allProducts is a large array, making the filter+re-render of ProductGrid noticeably slow. Why is setQuery called directly (not wrapped in startTransition) while setFiltered is wrapped?

javascript
function ProductSearch({ allProducts }) {
  const [query, setQuery] = useState('');
  const [isPending, startTransition] = useTransition();
  const [filtered, setFiltered] = useState(allProducts);

  function handleChange(e) {
    setQuery(e.target.value); // urgent — keep the input responsive
    startTransition(() => {
      setFiltered(allProducts.filter(p => p.name.includes(e.target.value)));
    });
  }

  return (
    <>
      <input value={query} onChange={handleChange} />
      {isPending && <span>Updating…</span>}
      <ProductGrid products={filtered} />
    </>
  );
}
AsetQuery needs to update immediately, at normal/urgent priority, so the <input> visually reflects each keystroke instantly with no lag; setFiltered (which drives the expensive ProductGrid re-render) is marked as a transition specifically so React can deprioritize it — keeping the input responsive even while the larger, slower list update is still being computed in the background, rather than the whole UI (including basic typing feedback) freezing until the filter finishes
BThere's no real reason — both calls should be wrapped in startTransition for consistency, and separating them is a mistake in this code
CsetQuery cannot be wrapped in startTransition at all — React throws an error if a <input>'s own controlling state setter is marked as a transition
DThe split is purely stylistic — isPending would report identically regardless of which setter is wrapped

None of fetchPosts or fetchStats actually needs data from the calls before them, yet theyre awaited sequentially. How long does `loadDashboard` take in total, and whats the fix?

javascript
async function loadDashboard() {
  const user = await fetchUser();       // 300ms
  const posts = await fetchPosts();     // 300ms — doesn't actually depend on `user`
  const stats = await fetchStats();     // 300ms — doesn't actually depend on `user` or `posts`
  return { user, posts, stats };
}
AThis already takes the minimum possible time — await always runs requests in parallel behind the scenes regardless of how they're written
BRoughly 300ms total, since JavaScript automatically parallelizes independent await calls that don't reference each other's results
CThis throws a runtime error, since multiple await statements cannot appear in the same function
DRoughly 900ms total (300 + 300 + 300) — each await fully blocks until its own request finishes before the next line even starts, creating a "waterfall" even though these three requests have no actual dependency on each other; the fix is Promise.all([fetchUser(), fetchPosts(), fetchStats()]), which starts all three requests at once and waits for all of them together — bringing the total time down to roughly 300ms (however long the slowest of the three takes), instead of their sum

Sign up free to play

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