Module 3: Frontend Frameworks & React
Why Frontend Frameworks Exist
Module 2 covered manipulating the DOM directly. At small scale that's fine — but as an app grows, manually finding elements and updating them in sync with changing data becomes error-prone and hard to maintain. Frameworks solve this by letting you describe what the UI should look like for a given piece of data, and handling the actual DOM updates for you.
Core ideas shared across almost every frontend framework:
- Components — small, reusable, self-contained pieces of UI
- State — data that changes over time and drives what's rendered
- Props — data passed into a component from its parent
- Reactive UI — when state changes, the UI updates automatically
- SPA (Single-Page App) — one HTML page whose content is swapped via JavaScript, instead of full page reloads between "pages"
React Basics: JSX, Components, Props & State
React is a JavaScript library (not a language, not a framework on its own) for building UIs out of components.
// JSX — HTML-like syntax written directly inside JavaScript
function Greeting({ name }) { // props are received as a function argument
return <h1>Hello, {name}!</h1>;
}
// Using it elsewhere
<Greeting name="Chiru" />
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // state — starts at 0
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
// Conditional rendering and lists — both just plain JavaScript inside JSX
function ItemList({ items, isLoading }) {
if (isLoading) return <p>Loading...</p>;
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
The key prop on list items helps React track which item is which across re-renders —
always use a stable, unique value (like a database ID), never the array index if the list can
reorder.
React Hooks
useState(initial) // local component state
useEffect(() => { ... }, [deps]) // run code in response to renders (data fetching, subscriptions)
useRef(initial) // a mutable value that persists without triggering re-renders
useMemo(() => calc(), [deps]) // cache an expensive calculation between renders
useCallback(fn, [deps]) // cache a function reference between renders
useContext(MyContext) // read shared data from a Context Provider, without prop-drilling
useEffect(() => {
fetch("/api/users")
.then(res => res.json())
.then(data => setUsers(data));
}, []); // empty array — runs once, after the first render
// Custom hooks — extract reusable logic out of a component, prefixed with "use"
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handler = () => setWidth(window.innerWidth);
window.addEventListener("resize", handler);
return () => window.removeEventListener("resize", handler); // cleanup
}, []);
return width;
}
React Router, Next.js & the React Ecosystem
React Router adds client-side routing to a React SPA — different URLs render different components, without a full page reload:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users/:id" element={<UserProfile />} />
</Routes>
Next.js is not a different language or a competitor to React — it's a framework built ON TOP of React, adding file-based routing, server-side rendering, and API routes, with a more opinionated, batteries-included structure than plain React + React Router.
Component architecture at scale typically separates presentational components from ones that hold state/data logic, keeps API calls in dedicated functions/hooks, and handles loading/error states explicitly around every async operation — patterns worth learning deliberately as an app grows past a handful of components. Testing React components commonly uses Testing Library (Module 3's Tooling chapter) to test behavior from a user's perspective rather than implementation details.
Vue, Angular, Svelte & Others
- Vue — approachable, template-based syntax, popular for its gentle learning curve and flexibility
- Angular — a full, opinionated, TypeScript-first framework maintained by Google, common in larger enterprise codebases
- Svelte — compiles components to highly optimized vanilla JS at build time, rather than shipping a runtime library to the browser
- Solid — React-like syntax with a fine-grained reactivity model, known for strong performance
- Preact — a much smaller, largely API-compatible alternative to React itself
- Lit — a lightweight library for building standards-based Web Components (covered in the JavaScript Everywhere chapter)
All of these solve the same core problem (components + reactive state) with different syntax and tradeoffs — React remains the most widely used in the broader JavaScript job market, which is why this course covers it in the most depth.