⚛ A JavaScript library for building user interfaces

React

Declarative, component-based, and learn-once-write-anywhere. An interactive deep-dive into the library that changed the web.

Concepts Components Hooks State & Props Virtual DOM Ecosystem
SCROLL

What makes React,
React?

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.

🧩

Component-Based

Build encapsulated components that manage their own state, then compose them to make complex UIs.

📣

Declarative

Describe what the UI should look like for any given state. React updates the DOM when your data changes.

🌊

Unidirectional Flow

Data flows down via props. Events bubble up via callbacks. Predictable, traceable, debuggable.

Virtual DOM

React keeps a lightweight in-memory representation of the DOM. Only real differences get applied.

🔁

Learn Once, Write Anywhere

React Native for mobile. React DOM for browsers. React Three Fiber for 3D. Same mental model everywhere.

🧪

Just JavaScript

No special template language. JSX compiles to plain JS function calls. The full power of JS, always available.

The building
blocks

A React component is a JavaScript function that returns JSX — a syntax extension that looks like HTML but compiles to React.createElement() calls.

Greeting.jsx
// 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>
  );
}

State & side effects
made simple

Introduced in React 16.8, Hooks let you use state and other React features inside functional components — no class required. They begin with use.

Counter.jsx
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.

DataFetcher.jsx
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.

theme.jsx
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.

FocusInput.jsx
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.

ExpensiveList.jsx
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.

useLocalStorage.js
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.

Data in motion

Props are read-only inputs passed from parent to child. State is private, mutable data owned by a component. Together they drive the UI.

Try it — live props

Type a name below and watch props flow to the child component in real-time.

<Parent />
name state:
─── props.name ──▶
<Child />
Hello, World!

Try it — useState counter

This is a live React-like counter powered by plain JS — showing the same update cycle.

// useState demo
0

Every component's
journey

React components are born, live, and die. Hooks map cleanly to these phases, replacing the old class-based lifecycle methods.

Mount
  • Component created
  • Initial render
  • DOM inserted
  • useEffect(fn, [])
Update
  • Props change
  • State changes
  • Re-render
  • useEffect(fn, [dep])
Unmount
  • Component removed
  • DOM cleaned up
  • Cleanup function
  • return () => {}
lifecycle-hooks.jsx
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

Reconciliation &
diffing

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.

Before update
<App>
<Header>
<h1> "Hello"
<List count=3>
<Item> "A"
<Item> "B"
<Item> "C"
After update
<App>
<Header>
<h1> "Hi there" ✦
<List count=4>
<Item> "A"
<Item> "B"
<Item> "C"
<Item> "D" ✦

React's reconciler only touches the highlighted nodes — the text content of <h1> and the new <Item> "D". Everything else is untouched.

The two golden
rules

Hooks have two non-negotiable rules. The React linter (eslint-plugin-react-hooks) enforces them automatically.

Beyond the core
library

React is intentionally minimal — it only handles the view layer. A rich ecosystem fills the gaps, giving you the right tool for every job.

Routing

React Router

Declarative client-side routing for single-page apps. v6+ uses hooks throughout.

Framework

Next.js

The React meta-framework. SSR, SSG, App Router, Server Components, and full-stack in one.

State

Zustand

Bear necessities for global state. Minimal boilerplate, hooks-first API, no providers needed.

State

TanStack Query

Server state management. Caching, background refetching, and optimistic updates with zero config.

Styling

Tailwind CSS

Utility-first CSS that pairs naturally with JSX's inline className approach.

UI

shadcn/ui

Accessible, unstyled component primitives you own — not a dependency you install.

Build

Vite

Blazing-fast dev server with HMR and optimized production builds. The modern replacement for CRA.

Testing

Testing Library

Tests that resemble how users interact with your app. Query by role, text, and label — not internals.

Native

React Native

Write React components that compile to native iOS and Android views. Truly native performance.