Frontend with React
Components, props, state, hooks, and the rendering model that runs millions of websites.
What is React?
React is a JavaScript library, created at Facebook in 2013, for building user interfaces. The core idea is dead simple: your UI is a function of state. Given some state, you describe what the UI should look like, and React figures out how to update the DOM to match.
Before React, frontend code was full of imperative DOM manipulation — `document.getElementById("foo").textContent = ...`. React replaced that with a declarative model: you write what you want, not how to update it.
JSX
React components are written in JSX — JavaScript with HTML-like syntax. JSX gets compiled to plain JS function calls. It's optional, but everyone uses it.
// JSX
const element = <h1 className="title">Hello, {name}!</h1>;
// What it compiles to:
const element = React.createElement("h1", { className: "title" }, "Hello, ", name, "!");Components
A component is a function that returns JSX. Components can be reused, nested, and given props (parameters).
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
function App() {
return (
<div>
<Welcome name="Ada" />
<Welcome name="Bob" />
</div>
);
}Conventions: component names start with a capital letter (so React knows they're components, not HTML tags). `className` instead of `class` (because `class` is a JS keyword).
State and the useState hook
Components can hold their own state — values that change over time and trigger re-renders. The `useState` hook is the most basic way to do this.
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}When you call `setCount`, React schedules a re-render. The component function runs again, `useState` returns the new value, and the JSX is re-built. React diffs the new JSX against the previous one and updates only the changed DOM nodes — the "virtual DOM" trick.
Side effects with useEffect
Anything that reaches outside the component — fetching data, subscribing to events, setting timers — is a "side effect". They go inside `useEffect`.
import { useEffect, useState } from "react";
function UserCard({ id }) {
const [user, setUser] = useState(null);
useEffect(() => {
let cancelled = false;
fetch(`/api/users/${id}`)
.then(r => r.json())
.then(data => { if (!cancelled) setUser(data); });
return () => { cancelled = true; }; // cleanup
}, [id]); // re-run whenever id changes
if (!user) return <p>Loading...</p>;
return <p>{user.name}</p>;
}The dependency array `[id]` is crucial. With no array, the effect runs after every render. With `[]`, only after the first. With `[id]`, only when `id` changes.
Rules of hooks
- Call hooks ONLY at the top level of a component or another hook. Never inside conditions, loops, or nested functions.
- Component names start with a capital letter; custom hooks start with `use`.
- If your component is small and pure (no state, no effects), you don't need any hooks.