React Web Development
Beginner-to-advanced React reference covering component design, JSX, state, events, forms, Hooks, effects, context, reducers, Suspense, errors, performance, accessibility, and testing.
Components, JSX & Rendering
Build pure component trees from immutable inputs.
Function Components, Props & JSX
Components are functions React calls. Props are immutable snapshots; JSX describes UI and embeds expressions with braces.
Render <Avatar /> rather than Avatar(). React must control component and Hook invocation to preserve identity and scheduling.
Given the same props, state, and context, rendering should produce the same result without mutating external values or starting side effects.
Conditional Rendering, Lists & Keys
Use normal JavaScript control flow. Keys identify siblings across insertion, deletion, and reordering.
Use stable domain IDs. Index and random keys can transfer local state to the wrong item or remount every child; key is not passed as a prop.
Composition, children & Slots
Compose specialized UI from smaller parts. Pass elements as children or named slots instead of building inheritance hierarchies.
Expose semantic props and slots that preserve component invariants. Avoid a large matrix of boolean appearance props or leaking internal DOM structure.
State, Events & Forms
Model state minimally and update it without mutation.
useState, Snapshots & Functional Updates
State belongs to a component position. Setting state queues a future render; current handlers retain the snapshot from the render that created them.
Mutating objects or arrays can leave React unaware of changes and corrupt previous snapshots. Create a new container and new changed values.
Minimal State, Derivation & Reset
Store the minimum source of truth; derive filtered, formatted, and aggregate values during rendering. Change a key to intentionally reset a subtree.
| State Kind | Preferred Home | Why | Example |
|---|---|---|---|
| Ephemeral component state | Nearest owning component | Keeps updates and lifetime local | Open menu, draft input |
| Shared subtree state | Closest common ancestor | Provides one source of truth to siblings | Selected item shared by list and detail |
| Widely shared stable context | Focused Context provider | Avoids deep prop threading | Theme, authenticated identity |
| Complex transition state | useReducer near its owner | Centralizes event-to-state rules | Multi-step form or editor |
| External mutable source | External store + useSyncExternalStore | Provides consistent concurrent subscriptions | Router or custom client cache |
| Derived value | Compute during render | Prevents synchronized duplicate state | Filtered rows or total price |
Do not mirror props or derived data into state with an Effect. It adds an extra render and creates stale synchronization bugs.
Events & Controlled Forms
Event handlers perform user-triggered work. Controlled fields receive value/checked plus a change handler from state.
A form and submit button provide keyboard, accessibility, and browser behavior. Avoid clickable divs and custom controls when native elements fit.
Hooks, Effects & Refs
Reuse stateful logic and synchronize only with systems outside React.
Rules of Hooks & Custom Hooks
Call Hooks only at the top level of React components or custom Hooks. Custom Hooks share logic, not state instances.
Do not call Hooks in conditions, loops, callbacks, or after conditional returns. React relies on identical call order to associate Hook state.
useEffect & Cleanup
Effects synchronize a component with external systems after commit. Dependencies must include every reactive value read by the effect.
If work can happen during render or in an event handler, it probably does not need an Effect. Framework data APIs are usually better for route data than manual fetch Effects.
Development may run setup, cleanup, then setup again to reveal missing cleanup. Fix the effect rather than suppressing the probe.
useRef, DOM Refs & Imperative Handles
Refs hold values not required for rendering and point to DOM nodes. Updating current does not re-render.
If a value affects output, store it in state. Reading/writing refs during rendering breaks purity except predictable one-time initialization.
Async UI, Actions, Suspense & Errors
Represent pending work and failure at explicit boundaries.
useTransition & useDeferredValue
Transitions mark non-urgent updates so urgent input stays responsive. Deferred values let a slow subtree lag behind a rapidly changing value.
They change scheduling priority and interruption behavior. Optimize expensive computation, data access, and bundle size separately.
Suspense & use
Suspense shows a fallback while supported children suspend. The use API reads a Promise or context and integrates with Suspense/error boundaries.
Suspense data contracts are best supplied by a framework or compatible cache. Creating a new Promise during every render causes repeated suspension.
Actions, Optimistic State & Error Boundaries
useActionState coordinates action result/pending state; useOptimistic shows immediate feedback. Error boundaries catch rendering failures below them, not event-handler errors.
Design pending identity, duplicate submission, server normalization, rejection, and rollback. Never imply irreversible success before the server commits it.
Performance, Accessibility & Testing
Measure before memoizing and test behavior through the user-visible surface.
memo, useMemo & useCallback
Memoization is a performance optimization. Use it when measured work or referential equality is important, not to make incorrect code function.
Dependency comparison, retained values, and complexity can cost more than recomputation. Profile production builds and first fix state placement, effects, and expensive rendering.
Accessibility & Safe DOM Output
Use semantic elements, labels, headings, focus management, keyboard behavior, and announced status/errors. React escapes text values by default.
dangerouslySetInnerHTML bypasses escaping. Sanitize untrusted HTML with a maintained policy and prefer structured rendering.
Testing & Production Checklist
Test output and interaction rather than component internals; preserve strict-mode compatibility and cleanup.
Query by role, label, and visible name; perform real events; assert rendered results. Avoid testing Hook call order, private state, or implementation-only selectors.