React Tutorial with Examples.
React tutorial with runnable examples: components, hooks, effects, the Rules of Hooks and the React Compiler, verified with real rendered and tested output.
Beginner
Start here — no prior experience needed
Your First React Component
Write a React component, render it to HTML with renderToString, and see JSX's real text-node separators and the falsy-zero rendering gotcha.
Props and Children
Pass data into components with props and default values, render arbitrary children, and count or map them with React's Children helpers.
Rendering Lists and the Key Warning
Render arrays with map, trigger React's real missing-key warning, then fix it — and see why an index key works but a stable id is safer.
State with useState
Render components with Vitest and Testing Library, click a real button with user-event, and prove two setState calls in one handler cause one render.
Handling Events
Wire onChange and onSubmit with real user-event clicks and keystrokes, and see jsdom's real warning when a form submit is never prevented.
Intermediate
For developers with core concepts down
Effects and useEffect
See StrictMode's real double-invoked mount effect, then a cleanup function that actually runs on unmount and before every dependency change.
You Might Not Need an Effect
Measure the extra render an effect adds when it only syncs derived state from props, then remove both the effect and the state entirely.
The Rules of Hooks
Call a hook conditionally and see React's real hook-order error and stack trace, then fix it by keeping every hook call unconditional.
useReducer and useContext
Test a cart reducer as a plain function with no rendering, then share it through context and prove the provider guard throws without one.
Custom Hooks
Extract reusable stateful logic into a custom hook, test it through a tiny host component, and give one an effect with real cleanup.
Measuring Re-renders: memo, useMemo, and useCallback
Count real re-renders with and without memo, see why memo alone fails with an inline callback, and measure useMemo skipping an expensive call.
Routing with React Router
Build a nested route tree with React Router 8's createMemoryRouter and RouterProvider, click a real Link in Vitest, and watch an unmatched URL render React Router's own 404 instead of a blank screen.
Portals with createPortal
Use createPortal to render a modal into document.body, prove in a real test that clicks still bubble through React's component tree instead of the DOM tree, and see the real error React throws when a portal reaches the server renderer.
Error Boundaries
Write a class-based error boundary, watch it catch a real render TypeError and show its fallback UI, then see the one error it never reaches: a throw inside an onClick handler, which React routes around componentDidCatch entirely.
Suspense and lazy
Split a component out with React.lazy and watch Suspense show a fallback until the real import() resolves, then spike two things the docs gloss over: nested boundary reveal order, and what a key on Suspense actually resets.
Reading Promises with use, No Framework Needed
Read a promise directly inside a component with React's use() hook, then spike the two ways it goes wrong: a plain render() that never catches up, and a promise recreated every render that never settles at all.
Retrying After an Error with react-error-boundary
Add a Retry button to a React error boundary with the react-error-boundary library's FallbackComponent and onReset, then watch a rejected promise read with use() land in the same boundary as a real thrown error.
Advanced
Production-grade patterns for experienced engineers
The React Compiler
Run babel-plugin-react-compiler on real source, read the auto-memoized output it writes, and measure the re-renders it actually skips versus a bailout.
Actions and useActionState
Wire a <form action={fn}> to useActionState, watch isPending flip false-true-false across a real submission, return an error instead of throwing one, and learn why user-event needs a clear() after React resets the form.
Actions Outside a Form: startTransition and the Queue
Call an action outside any <form> by wrapping it in startTransition, watch two back-to-back clicks queue instead of racing, see the real warning for skipping startTransition, and confirm whether a thrown error wipes out a queued action waiting behind it.
useOptimistic and useFormStatus
Show the new value from useOptimistic before a save actually finishes, watch it roll back to the real value when the save rejects, and read a form's pending state in a child SubmitButton with useFormStatus instead of passing a prop down to it.
Route Loaders and Error Elements
Add a loader to a React Router 8 route, watch it log on every navigation, throw the data() helper for a 404 scoped to just that route, then reproduce and fix the real HydrateFallback warning the previous lesson's routes deliberately avoided.
Also part of React
Taught in other topics. Each link opens the lesson in its home topic.
Testing JavaScript with Jest and Vitest
Learn how to write reliable unit tests in JavaScript using Jest and Vitest — from basic assertions to mocking, async tests, and code coverage.
React with TypeScript
Type React 19 props, children, hooks, events, context and generic components, verified with real tsc errors and server-rendered output from tsx.
Server and Client Components
A Server Component that imports useState fails a real Next.js 16 build; adding use client fixes it, and a console.log proves where each component ran.
Server Actions
A Server Action wired to a form is a real POST endpoint: curl submits it, server validation rejects bad input, and updateTag reflects the change at once.
Dynamic by Default: Rendering Modes
A Next.js 16 page reading connection() outside Suspense fails a real build; wrapping it in Suspense streams a hole, and instant = false blocks instead.