Profiling & Optimization

Preview — 3 of 10 questions

How does startTransition prevent UI freezes?

javascript
function FilterPage() {
  const [filterText, setFilterText] = useState("");
  const [filteredList, setFilteredList] = useState(allItems);
  const [isPending, startTransition] = useTransition();

  const handleChange = (e) => {
    const value = e.target.value;
    setFilterText(value); // urgent: update input immediately

    startTransition(() => {
      setFilteredList(filterItems(allItems, value)); // non-urgent: can lag
    });
  };

  return (
    <>
      <input value={filterText} onChange={handleChange} />
      <div style={{ opacity: isPending ? 0.7 : 1 }}>
        {filteredList.map(item => <ItemCard key={item.id} item={item} />)}
      </div>
    </>
  );
}
AstartTransition debounces the state update by 300ms
BstartTransition marks updates as non-urgent — React can interrupt and restart them if a higher-priority update arrives; the input stays responsive while the list render happens in the background
CstartTransition runs the callback in a Web Worker
DstartTransition delays the update until the browser is idle (like requestIdleCallback)

When should you use useDeferredValue over useTransition?

javascript
function SearchResults({ query }) {
  const deferredQuery = useDeferredValue(query);

  // Expensive: processes/renders 10,000 items
  const results = useMemo(
    () => filterItems(allItems, deferredQuery),
    [deferredQuery]
  );

  const isStale = query !== deferredQuery;

  return (
    <div style={{ opacity: isStale ? 0.6 : 1 }}>
      {results.map(r => <ResultRow key={r.id} result={r} />)}
    </div>
  );
}

// Parent:
function SearchPage() {
  const [query, setQuery] = useState("");
  return (
    <>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <SearchResults query={query} />
    </>
  );
}
AuseDeferredValue should replace all useState calls
BuseDeferredValue is for deferring a VALUE you receive (from props or context); useTransition is for deferring a state UPDATE you control; here the parent owns the state — use useDeferredValue in the child
CuseDeferredValue is equivalent to setTimeout(fn, 0) for the value
DYou need both useDeferredValue AND useTransition in this example

What does the React Compiler (React 19+) eliminate?

javascript
// Before React Compiler — manual memoization needed:
function ProductList({ products, onBuy }) {
  const sorted = useMemo(
    () => [...products].sort((a, b) => a.price - b.price),
    [products]
  );
  const handleBuy = useCallback((id) => onBuy(id), [onBuy]);

  return sorted.map(p => (
    <ProductCard key={p.id} product={p} onBuy={handleBuy} />
  ));
}

// After React Compiler — automatic:
function ProductList({ products, onBuy }) {
  const sorted = [...products].sort((a, b) => a.price - b.price);
  const handleBuy = (id) => onBuy(id);
  return sorted.map(p => <ProductCard key={p.id} product={p} onBuy={handleBuy} />);
}
AReact Compiler converts JavaScript to a different language
BReact Compiler only optimizes class components
CReact Compiler automatically infers which values and functions need memoization — it inserts the equivalent of useMemo/useCallback at compile time, eliminating most manual optimization
DReact Compiler requires TypeScript to work

Sign up free to play

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