Deck 7 - Performance + Rendering + React Internals (objective)
Goal: identify render/perf footguns and propose fixes that improve responsiveness without cargo-cult memoization.
You practice: reconciliation, keys, memo/useMemo/useCallback, transitions, Suspense/code-splitting, and effect timing.
Output style: 1 verdict sentence + 2-3 issues + best fix approach.
Render vs commit (mental model).
Reconciliation and keys (why keys matter).
Batching (what it means).
What triggers rerenders?
React.memo (when it helps).
useMemo (when it helps).
useCallback (when it helps).
Referential equality (core idea).
Avoid expensive work in render.
List performance (virtualization).
Transitions (useTransition/startTransition).
useDeferredValue (when).
Suspense + code splitting (baseline).
Effect timing (useEffect vs useLayoutEffect).
Infinite loops (common causes).
Context performance (gotcha).
SSR/hydration mismatch (baseline).
Measuring performance (tools).
Evaluator wording for perf issues.
Name the root cause (unnecessary rerenders/expensive render work/unstable identity), impact (jank/slow typing), fix (memoize correctly, split work, transition, virtualize).
Gotcha: using array index as key in a reorderable list.
items.map((item, i) => <Row key={i} item={item} />)Verdict: FAIL
- Issue: index keys break identity on reorder.
- Impact: wrong state/DOM reuse + extra churn.
- Fix: use stable unique key (item.id).
Gotcha: key missing entirely.
items.map(item => <Row item={item} />)Verdict: FAIL
- Issue: missing key.
- Fix: add key={item.id}.
Gotcha: sorting in render every time.
const sorted = items.slice().sort((a,b) => a.name.localeCompare(b.name)); return sorted.map(...);
Verdict: PARTIAL FAIL
- Issue: expensive work on every render.
- Fix: useMemo with correct deps or pre-sort upstream.
Gotcha: filtering huge list on every keystroke.
const filtered = items.filter(x => x.name.includes(q));
Verdict: PARTIAL FAIL
- Issue: expensive synchronous work blocks typing.
- Fix: useDeferredValue/useTransition and/or debounce + memoization.