React
Rebuild your instincts for how React actually works: reconciliation, effects, memoization, and the concurrent/server-component model that quietly changed the rules.
70 concepts418 live tasks
Start practicing freeWhat's inside
Rendering Model & Reconciliation
JSX produces cheap descriptions, not component instances
Render computes; commit mutates
Render must be pure: concurrent React enforces what was always the deal
Components re-render because their parent did, not because props changed
Reconciliation keys off element type and position
State belongs to a position in the tree, not to the component
key tells React which item is which: index keys lie under reordering
Changing key is the sanctioned way to reset a component
Not all updates are equal: React schedules work in priority lanes
Components, Props & Composition
children is a prop, and passing JSX through it is a rendering firewall
Most prop drilling is a composition problem, not a context problem
Defining a component inside another component remounts it every render
Controlled means React state is the source of truth: pick one and don't drift
Render props: inversion of control that hooks didn't fully replace
Compound components: an API where the JSX structure is the configuration
Why your list renders a stray 0
State & Updates
setState doesn't change the variable: it requests a render
setState(fn) reads the queue, not the snapshot
React 18 batches everywhere: flushSync is the escape hatch
useState(expensive()) runs every render; useState(() => expensive()) runs once
React compares state with Object.is: mutation makes changes invisible
If you can compute it during render, it isn't state
useReducer when the next state is a function of what happened
Effects & Synchronization
useEffect is synchronization, not componentDidMount in a trench coat
The dependency array isn't a trigger config: lying to it creates stale worlds
The interval that logs 1 forever
Cleanup runs before every re-run: with the previous render's values
StrictMode mounts, unmounts, and remounts on purpose
Two in-flight fetches, last response wins (and it's not always the last request)
Most effects are one of two mistakes: derived data or delayed events
useLayoutEffect blocks paint; useEffect doesn't
Effect events: read the latest values without re-triggering the effect
Hooks Rules & Custom Hooks
Hooks have no names: call order is the only index
You can't skip a hook, so restructure until you don't need to
Every call to a custom hook gets its own state
Memoized callbacks are snapshots too
A custom hook that returns a fresh object every render poisons every consumer
useId exists because random IDs break hydration
use() bends the rules: conditional reads of promises and context
Refs, DOM & Imperative Escape Hatches
useRef is a render-surviving box that doesn't notify anyone
Refs during render: don't read, don't write
Callback refs run at attach and detach, and can return cleanup
ref was never a normal prop; forwardRef bridged it, React 19 retires it
useImperativeHandle: publish a contract, not a DOM node
Portals move the DOM, not the React tree
Context & State Architecture
Context re-renders every consumer on every value change: no partial subscriptions
value={{ user, login }} re-renders every consumer on every provider render
Split contexts: components that only dispatch shouldn't re-render on state
Why context has no selectors, and how store libraries escape React to get them
State wants to live next to its consumers: lift late, push down early
useReducer + context: the built-in store pattern
Server data is a cache, not state: stop useState-ing API responses
The createContext default only applies when there's no provider above
Performance & Memoization
Re-renders are innocent until profiled guilty
memo() compares props with Object.is, one level deep
Why memo() dies the moment you pass children
useMemo, useCallback, and memo() only work as an unbroken chain
useMemo is a performance hint React is allowed to ignore
10,000 DOM nodes is the problem no memo can fix
The Profiler measures commits: learn to read 'why did this render?'
React Compiler memoizes for you, by enforcing the rules you claimed to follow
Concurrent React & Server Components
Concurrent rendering: work that can be paused, abandoned, and restarted
Suspense: components declare what they're waiting for; boundaries decide what shows
Transitions mark updates as interruptible, and what's in scope is subtler than it looks
useDeferredValue: let a derived tree lag behind an urgent input
Tearing: when half your UI renders one store version and half another
'use client' marks a boundary, not a component
Props crossing the server/client boundary must survive serialization
Hydration errors: server HTML and first client render must be identical
Streaming SSR: send the shell now, the slow parts later, hydrate what's touched first

