The React framework

Contents

  • Section 1 · What is React? — History, philosophy, and ecosystem overview
  • Section 2 · Core Concepts — JSX, components, props, and state
  • Section 3 · Application Structure — Project layout, tooling, and build pipeline
  • Section 4 · React Hooks — useState, useEffect, useContext, and custom hooks
  • Section 5 · Component Patterns — Composition, lifting state, and controlled components
  • Section 6 · React Ecosystem — Routing, state management, and styling solutions
  • Section 7 · Why React? — Performance model, DX benefits, and industry adoption
  • Section 8 · Summary & Further Reading

Section 1. What is React?

History & Context

  • Created at Facebook (now Meta); first open-sourced at JSConf US in May 2013
  • Born out of the need to build large-scale, data-driven UIs (Facebook News Feed, Instagram)
  • Introduced a fundamentally different mental model: UI as a function of state
  • Today it is maintained by Meta and a large open-source community
  • Current stable release: React 19 (2024) — introducing Server Components and Actions
  • One of the most widely adopted front-end libraries in the industry

React's Core Philosophy

  • Declarative — describe what the UI should look like, not how to manipulate the DOM
  • Component-Based — encapsulate UI into self-contained, reusable pieces
  • Learn Once, Write Anywhere — same mental model for web (ReactDOM) and mobile (React Native)
  • Unidirectional data flow — data flows from parent → child, making state predictable

// Declarative: React handles the DOM
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// Usage
<Greeting name="Alice" />

// React reconciles DOM changes
// automatically — no querySelector,
// no innerHTML manipulation needed
					

Section 2.Core Concepts

JSX — JavaScript XML

  • JSX is a syntax extension that lets you write HTML-like markup inside JavaScript
  • Transpiled to React.createElement() calls by Babel or the React compiler
  • Expressions inside {} are evaluated as JavaScript
  • className instead of class; htmlFor instead of for
  • Self-closing tags are mandatory: <img />, <br />

// JSX syntax
const element = (
	<div className="card">
	<h2>{user.name}</h2>
	<p>Score: {user.score * 2}</p>
	{user.isAdmin && <Badge />}
	</div>
);

// What Babel compiles it to:
const element = React.createElement(
	"div",
	{ className: "card" },
	React.createElement("h2", null, user.name)
);						
					

Components — Building Blocks of React

  • A component is a JavaScript function that returns JSX
  • Component names must start with a capital letter
  • Two flavours: Function Components (modern) and Class Components (legacy)
  • Components can be composed — placed inside other components
  • Each component has its own isolated state and lifecycle

// Function component (recommended)
function UserCard({ name, role }) {
	return (
	<div className="card">
		<Avatar name={name} />
		<h3>{name}</h3>
		<span>{role}</span>
	</div>
	);
}

// Composition
function App() {
	return (
	<main>
		<UserCard name="Alice" role="Admin" />
		<UserCard name="Bob"   role="Editor" />
	</main>
	);
}
					

Props — Passing Data Down

  • Props (properties) are the mechanism for passing data from parent to child
  • Props are read-only — a component must never modify its own props
  • Any JavaScript value can be a prop: string, number, array, object, function, or JSX
  • Default prop values can be specified with destructuring defaults
  • PropTypes or TypeScript can be used for type safety

function Button({ label, onClick, variant = "primary" }) {
	return (
		<button
		className={`btn btn--${variant}`}
		onClick={onClick}
		>
		{label}
		</button>
	);
	}
	
	// Parent passes props
	<Button
	label="Save"
	variant="secondary"
	onClick={() => handleSave()}
	/>
	
// Children prop
<Panel>
  <p>Any JSX can be a child.</p>
</Panel>

				  

State — Local, Mutable Data

  • State is data that can change over time and triggers a re-render when updated
  • useState hook returns [currentValue, setterFunction]
  • State updates are asynchronous and batched for performance
  • Never mutate state directly — always use the setter function
  • State is local to the component instance by default

import { useState } from "react";

function Counter() {
	const [count, setCount] = useState(0);

	function increment() {
	setCount(prev => prev + 1); // functional update
	}

	return (
	<div>
		<p>Count: {count}</p>
		<button onClick={increment}>+1</button>
		<button onClick={() => setCount(0)}>
		Reset
		</button>
	</div>
	);
}										
					

Section 3. Application Structure

Project Layout — Vite + React


my-app/
	├── index.html              Entry HTML — mounts the React root
	├── vite.config.js          Build tool configuration
	├── package.json            Dependencies and scripts
	└── src/
			├── main.jsx           Bootstrap — ReactDOM.createRoot()
			├── App.jsx            Root component
			├── components/        Reusable, dumb UI components
			├── pages/             Route-level components
			├── hooks/             Custom React hooks
			├── context/           React Context providers
			└── assets/            Images, fonts, static files
					

Bootstrapping a React App

  • Vite is the recommended build tool — fast HMR and optimised production bundles
  • create-react-app is deprecated; Vite or Next.js are the current standards
  • ReactDOM.createRoot() mounts the component tree into the HTML DOM
  • React.StrictMode enables additional runtime warnings in development

// Terminal
npm create vite@latest my-app -- --template react
cd my-app && npm install && npm run dev

// src/main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";

ReactDOM.createRoot(
	document.getElementById("root")
).render(
	<React.StrictMode>
	<App />
	</React.StrictMode>
);						
					

Tooling Ecosystem. Development Tools

  • Vite — lightning-fast dev server with HMR
  • Babel / SWC — JSX & modern JS transpilation
  • ESLint — static analysis and React-specific rules
  • Prettier — consistent code formatting
  • TypeScript — optional static typing (highly recommended)
  • Vitest / Jest — unit and integration testing
  • React Testing Library — DOM-centric component tests
  • Storybook — isolated component development

Tooling Ecosystem. Deployment & Quality

  • React DevTools — browser extension for component inspection
  • Vite Preview — locally serve production build
  • npm / pnpm / yarn — package managers
  • GitHub Actions / CI — automated testing & deployment
  • Vercel / Netlify — zero-config React deployment
  • Docker — containerised production environments

Section 4. React Hooks

What Are Hooks?

  • Introduced in React 16.8 (2019) — allow function components to use React features
  • Replace lifecycle methods (componentDidMount, componentDidUpdate, …) from class components
  • Rules of Hooks: only call at the top level; only call from React functions
  • Built-in hooks: useState, useEffect, useContext, useReducer, useMemo, useCallback, useRef, …
  • Custom hooks: extract reusable stateful logic into plain functions prefixed with 'use'

useEffect — Side Effects & Lifecycle

  • Runs after every render by default
  • Dependency array [] controls when effect re-runs
  • Return a cleanup function to avoid memory leaks
  • Use cases: data fetching, subscriptions, manual DOM mutations, timers

import { useState, useEffect } from "react";

function UserProfile({ userId }) {
const [user, setUser] = useState(null);

useEffect(() => {
let cancelled = false;

fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => {
if (!cancelled) setUser(data);
});

return () => { cancelled = true; }; // cleanup
}, [userId]); // re-run when userId changes

if (!user) return <p>Loading…</p>;
return <h1>{user.name}</h1>;
}
					

useContext — Avoiding Prop Drilling

  • Context provides a way to share values across the component tree without explicit props
  • createContext() defines the context; Provider wraps the subtree
  • useContext(MyContext) consumes the nearest Provider value
  • Common uses: theme, locale, current user, auth state
  • For complex global state, consider Zustand or Redux Toolkit instead

// ThemeContext.jsx
import { createContext, useContext, useState } from "react";

const ThemeContext = createContext("light");

export function ThemeProvider({ children }) {
  const [theme, setTheme] = useState("light");
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Consuming component (anywhere in tree)
function Header() {
  const { theme, setTheme } = useContext(ThemeContext);
  return <button onClick={() => setTheme(
    theme === "light" ? "dark" : "light"
  )}>Toggle</button>;
}
					

Custom Hooks — Reusable Logic

  • A custom hook is any function starting with 'use' that calls other hooks
  • Encapsulate repetitive stateful patterns (fetch, form handling, media query, …)
  • Shareable across components without changing the component tree
  • Can be published as npm packages (react-use, ahooks, …)

// hooks/useFetch.js
import { useState, useEffect } from "react";

export function useFetch(url) {
	const [data, setData]       = useState(null);
	const [loading, setLoading] = useState(true);
	const [error, setError]     = useState(null);

	useEffect(() => {
	setLoading(true);
	fetch(url)
		.then(r => r.json())
		.then(setData)
		.catch(setError)
		.finally(() => setLoading(false));
	}, [url]);

	return { data, loading, error };
}

// Usage in a component
const { data, loading } = useFetch("/api/posts");
					

Section 5. Component Patterns

Lifting State Up

  • When two sibling components need to share state, move it to their common parent
  • The parent owns the state; children receive it as props
  • Children can request changes by calling callback props
  • This is a fundamental pattern — master it before reaching for global state

function TemperatureApp() {
  const [celsius, setCelsius] = useState(0);
  const fahrenheit = celsius * 9/5 + 32;

  return (
    <div>
      <CelsiusInput
        value={celsius}
        onChange={setCelsius}
      />
      <FahrenheitDisplay value={fahrenheit} />
    </div>
  );
}

// Child — controlled by parent
function CelsiusInput({ value, onChange }) {
  return (
    <input
      type="number"
      value={value}
      onChange={e => onChange(Number(e.target.value))}
    />
  );
}
					

Controlled vs Uncontrolled Components

  • Controlled: React state is the single source of truth for form values
  • Uncontrolled: DOM manages its own state; React reads via refs when needed
  • Controlled components are easier to validate, test, and synchronise
  • useRef() provides a mutable container that does not trigger re-renders

// Controlled input
function ControlledForm() {
  const [email, setEmail] = useState("");

  function handleSubmit(e) {
    e.preventDefault();
    console.log(email);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={email}
        onChange={e => setEmail(e.target.value)}
        type="email"
      />
      <button type="submit">Send</button>
    </form>
  );
}

// Uncontrolled — use sparingly
function UncontrolledForm() {
  const inputRef = useRef(null);
  return <input ref={inputRef} />;
}
					

Section 6. The React Ecosystem

Routing & Navigation

React Router v6

  • React Router v6 — most popular client-side router
  • Nested routes and layout routes via <Outlet />
  • Loaders and actions for data fetching (v6.4+)
  • TanStack Router — type-safe alternative with file-based routing
  • Next.js App Router — server-side and hybrid routing

Key Concepts

  • import { BrowserRouter, Routes, Route } from 'react-router-dom'
  • <Routes> replaces the old <Switch>
  • useNavigate() for programmatic navigation
  • useParams() to read URL parameters
  • useSearchParams() for query strings
  • Protected routes via wrapper components

State Management Landscape

Solutions

  • useState / useReducer — local component state (start here)
  • Context API — lightweight cross-tree sharing, no extra deps
  • Zustand — minimal, ergonomic global store (~1 KB)
  • Redux Toolkit — predictable, testable, for complex apps
  • Jotai / Recoil — atomic state management
  • TanStack Query — server-state: caching, refetching, mutations

Guidance

  • Rule of thumb: don't reach for global state prematurely
  • Server state (API data) ≠ client state (UI flags) — manage separately
  • TanStack Query eliminates most 'global state' needs by caching server data
  • Redux is often unnecessary for small-to-medium apps
  • Zustand is an excellent middle ground

Styling Approaches

  • Plain CSS / CSS Modules — zero runtime overhead; scoped with [name].module.css
  • Tailwind CSS — utility-first, widely adopted, pairs well with React component model
  • CSS-in-JS (styled-components, Emotion) — dynamic styles with JS; higher runtime cost
  • Sass/SCSS — variables, nesting, mixins; compiles to plain CSS
  • Radix UI / shadcn/ui — headless, accessible component primitives
  • Choosing a strategy: CSS Modules or Tailwind recommended for new projects in 2024

Section 7. Why React?

The Virtual DOM & Reconciliation

  • React maintains a lightweight in-memory copy of the DOM — the Virtual DOM
  • When state changes, React renders a new Virtual DOM tree and diffs it with the previous one
  • Only the minimal set of real DOM mutations are applied (reconciliation / diffing algorithm)
  • Keys help React identify which list items changed, were added, or removed
  • React 18 introduced concurrent rendering — React can interrupt, pause, and resume rendering
  • Automatically Memoized Compiler (React 19) removes the need for manual useMemo/useCallback

Developer Experience Benefits

Developer Experience
  • Component model maps naturally to design systems and UI kits
  • Hot Module Replacement — instant feedback without page reload
  • React DevTools — inspect component tree, props, and state live
  • Rich TypeScript support via @types/react
  • Massive open-source ecosystem: thousands of compatible libraries
  • AI-assisted development — LLMs produce high-quality React code
Industry Adoption
  • Facebook, Instagram, WhatsApp Web (Meta)
  • Netflix, Airbnb, Atlassian, Dropbox
  • GitHub (partial), Notion, Linear
  • Used by ~40% of JavaScript developers (Stack Overflow 2023)
  • Strong hiring market — React is the #1 requested front-end skill
  • Stable API — core concepts from 2018 still apply today