⚛ A JavaScript library for building user interfaces
Declarative, component-based, and learn-once-write-anywhere. An interactive deep-dive into the library that changed the web.
// 01 — Core Concepts
React was created by Jordan Walke at Facebook in 2013. It introduced a revolutionary approach to building UIs — instead of manipulating the DOM directly, you describe what the UI should look like, and React figures out how to get there.
Build encapsulated components that manage their own state, then compose them to make complex UIs.
Describe what the UI should look like for any given state. React updates the DOM when your data changes.
Data flows down via props. Events bubble up via callbacks. Predictable, traceable, debuggable.
React keeps a lightweight in-memory representation of the DOM. Only real differences get applied.
React Native for mobile. React DOM for browsers. React Three Fiber for 3D. Same mental model everywhere.
No special template language. JSX compiles to plain JS function calls. The full power of JS, always available.
// 02 — Components
A React component is a JavaScript function that returns JSX — a syntax extension that looks like HTML but compiles to React.createElement() calls.
// A simple functional component function Greeting({ name, role }) { return ( <div className="card"> <h2>Hello, {name}!</h2> <p className="role">{role}</p> </div> ); } // Composed into a parent component function Team() { return ( <section> <Greeting name="Ada" role="Engineer" /> <Greeting name="Grace" role="Architect" /> <Greeting name="Linus" role="Kernel Dev" /> </section> ); }
// 03 — Hooks
Introduced in React 16.8, Hooks let you use state and other React features inside functional components — no class required. They begin with use.
import { useState } from 'react'; function Counter() { // [currentValue, setter] = useState(initialValue) const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>+</button> <button onClick={() => setCount(c => c - 1)}>−</button> </div> ); }
Every call to setCount triggers a re-render. React batches multiple state updates in event handlers for performance.
import { useState, useEffect } from 'react'; function DataFetcher({ userId }) { const [user, setUser] = useState(null); useEffect(() => { // Runs after render when userId changes let active = true; fetchUser(userId).then(data => { if (active) setUser(data); }); // Cleanup: cancel stale requests return () => { active = false; }; }, [userId]); // dependency array return user ? <Profile user={user} /> : <Spinner />; }
The dependency array controls when the effect re-runs. Empty [] = once on mount. Omit it = every render.
import { createContext, useContext } from 'react'; const ThemeCtx = createContext('light'); function App() { return ( <ThemeCtx.Provider value="dark"> <Sidebar /> {/* deeply nested */} </ThemeCtx.Provider> ); } function Sidebar() { // No prop drilling needed! const theme = useContext(ThemeCtx); return <div className={theme}>...</div>; }
Context solves prop drilling — passing values through many layers. Best for truly global data: themes, auth, locale.
import { useRef } from 'react'; function FocusInput() { // ref.current = the actual DOM node const inputRef = useRef(null); const handleClick = () => { inputRef.current.focus(); }; return ( <> <input ref={inputRef} /> <button onClick={handleClick}>Focus</button> </> ); }
useRef persists a mutable value across renders without triggering re-renders. Perfect for DOM access, timers, and previous value tracking.
import { useMemo, useCallback } from 'react'; function ExpensiveList({ items, filter }) { // Only recalculates when items or filter changes const filtered = useMemo( () => items.filter(i => i.name.includes(filter)), [items, filter] ); // Stable function reference across renders const handleSelect = useCallback( (id) => selectItem(id), [] ); return filtered.map(i => <Item key={i.id} onSelect={handleSelect} />); }
Use useMemo to cache expensive computations and useCallback to memoize function references. Don't reach for these prematurely — profile first.
import { useState } from 'react'; // Custom hook — reusable stateful logic function useLocalStorage(key, initial) { const [value, setValue] = useState(() => { try { const stored = localStorage.getItem(key); return stored ? JSON.parse(stored) : initial; } catch { return initial; } }); const set = (v) => { setValue(v); localStorage.setItem(key, JSON.stringify(v)); }; return [value, set]; }
Any function starting with use that calls other hooks is a custom hook. They let you extract and share stateful logic without changing component hierarchies.
// 04 — State & Props
Props are read-only inputs passed from parent to child. State is private, mutable data owned by a component. Together they drive the UI.
Type a name below and watch props flow to the child component in real-time.
This is a live React-like counter powered by plain JS — showing the same update cycle.
// 05 — Lifecycle
React components are born, live, and die. Hooks map cleanly to these phases, replacing the old class-based lifecycle methods.
useEffect(() => { console.log('mount'); return () => console.log('unmount'); }, []); // ← empty array = mount/unmount only useEffect(() => { console.log('count changed to', count); }, [count]); // ← runs when count updates
// 06 — Virtual DOM
React maintains a Virtual DOM — a lightweight JavaScript object tree mirroring the actual DOM. On each state change, React diffs the new tree against the old one and applies only the minimal set of real DOM changes.
React's reconciler only touches the highlighted nodes — the text content of <h1> and the new <Item> "D". Everything else is untouched.
// 07 — Rules of Hooks
Hooks have two non-negotiable rules. The React linter (eslint-plugin-react-hooks) enforces them automatically.
Never call hooks inside loops, conditions, or nested functions. This ensures hooks are called in the same order every render — which is how React tracks which state belongs to which hook.
Call hooks from React functional components or from custom hooks only — never from plain JavaScript functions, class components, or event handlers.
// 08 — Ecosystem
React is intentionally minimal — it only handles the view layer. A rich ecosystem fills the gaps, giving you the right tool for every job.
Declarative client-side routing for single-page apps. v6+ uses hooks throughout.
The React meta-framework. SSR, SSG, App Router, Server Components, and full-stack in one.
Bear necessities for global state. Minimal boilerplate, hooks-first API, no providers needed.
Server state management. Caching, background refetching, and optimistic updates with zero config.
Utility-first CSS that pairs naturally with JSX's inline className approach.
Accessible, unstyled component primitives you own — not a dependency you install.
Blazing-fast dev server with HMR and optimized production builds. The modern replacement for CRA.
Tests that resemble how users interact with your app. Query by role, text, and label — not internals.
Write React components that compile to native iOS and Android views. Truly native performance.