Intermediate
Quick reference for React — hooks API, JSX and props, controlled forms, custom hooks, rules of hooks, and React 19 features like Actions, use, and useOptimistic.
HooksJSXStateComponents
Component & JSX
function Card({ title, children }) {
return (
<>
<h2 className="t">{title}</h2> {/* className, not class */}
{children} {/* composition */}
{cond && <Badge />} {/* conditional */}
{cond ? <A /> : <B />} {/* ternary */}
</>
);
}
// Capitalized name, single root, pure render, onClick camelCase
Hooks Reference
| Hook | Purpose |
| useState | local state + re-render |
| useEffect | sync with external system |
| useContext | read shared context |
| useReducer | complex state transitions |
| useMemo | cache a computed value |
| useCallback | cache a function ref |
| useRef | mutable value / DOM node |
| useActionState | form action + pending (19) |
| useOptimistic | optimistic UI (19) |
| use | read promise/context (19) |
State
const [n, setN] = useState(0);
const [s, setS] = useState(() => init()); // lazy init
setN(n + 1); // value from this render
setN(c => c + 1); // functional updater (latest)
setObj(o => ({ ...o, k: v })); // never mutate — new object
setArr(a => [...a, item]); // new array
Effects
| Deps | When it runs |
| [a, b] | mount + a/b change |
| [] | once on mount |
| none | every render |
useEffect(() => {
const ctrl = new AbortController();
fetch(url, { signal: ctrl.signal }).then(/* ... */);
return () => ctrl.abort(); // cleanup before re-run / unmount
}, [url]);
Reducer & Context
function reducer(state, action) {
switch (action.type) {
case 'inc': return state + 1;
default: return state;
}
}
const [count, dispatch] = useReducer(reducer, 0);
dispatch({ type: 'inc' });
const Ctx = createContext(defaultVal);
<Ctx.Provider value={v}>{children}</Ctx.Provider>
const v = useContext(Ctx);
Memo, Callback & Ref
const v = useMemo(() => expensive(a, b), [a, b]);
const f = useCallback((x) => doThing(x), [dep]);
const ref = useRef(null); // { current: null }
<input ref={ref} />
ref.current?.focus(); // no re-render on change
// React 19: ref is a plain prop, no forwardRef needed
Lists & Controlled Forms
{items.map(i => <li key={i.id}>{i.name}</li>)} // stable id, not index
const [v, setV] = useState('');
<input value={v} onChange={e => setV(e.target.value)} />
<form onSubmit={e => { e.preventDefault(); submit(v); }}>
Custom Hook
function useToggle(initial = false) {
const [on, setOn] = useState(initial);
const toggle = useCallback(() => setOn(o => !o), []);
return [on, toggle] as const;
}
// Starts with `use`, calls hooks, shares logic not state
Rules of Hooks
- Call hooks only at the top level — never in loops, conditions, or nested functions.
- Call hooks only from components or other custom hooks.
- Order must be stable across renders (React tracks state by call order).
- Lift state to the closest common ancestor to share between siblings.
React 19
// Actions + useActionState
const [err, action, pending] = useActionState(async (prev, fd) => {
return await save(fd.get('name'));
}, null);
<form action={action}><button disabled={pending}>Save</button></form>
// use — read a promise or context during render (can be conditional)
const data = use(dataPromise);
// useOptimistic — instant UI while action is pending
const [optimistic, add] = useOptimistic(list, (s, x) => [...s, x]);
// Server Component (async, no state/effects)
async function Page() { const d = await db.query(); return <List d={d} />; }
// 'use client' at top of file opts into client interactivity