What is React? The JavaScript Library That Changed Frontend Development
React is a JavaScript library for building user interfaces. Facebook built it in 2013, open-sourced it, and the entire frontend ecosystem reorganized itself around it. Here is how the component model works, why it took over, and what you need to know before writing a single line.
React is a JavaScript library for building user interfaces. Facebook built it in 2013, open-sourced it, and the entire frontend ecosystem reorganized itself around it.
That's the short version. The longer version involves a paradigm shift in how you think about UIs, a component model that every major framework copied, and a virtual DOM that developers argued about for years before mostly deciding it wasn't the main point anyway.
If you're building anything on the web in 2026 and you haven't run into React, you've been working in a very specific corner. It's not the only option, but it's the one most companies default to. Knowing it matters.
The Problem React Was Built to Solve
Before React, building interactive UIs meant manually manipulating the DOM. You'd select elements, update their content, add event listeners, track state in scattered variables, and hope nothing got out of sync. jQuery helped manage the DOM selection part. It didn't touch the deeper problem: as applications grew, the relationship between your data and your UI became impossible to reason about.
Facebook had this problem at scale. Their news feed, notifications, chat, and ads all needed to update dynamically without full page refreshes. The old approach of "find the DOM node and update it" broke down when fifty different pieces of code could touch the same UI elements.
Their solution: stop thinking about updating the UI and start thinking about describing what the UI should look like given the current state. React would figure out the DOM mutations.
The Core Model
React applications are built from components. A component is a JavaScript function that returns UI.
function Button({ label, onClick }) {
return (
<button onClick={onClick}>
{label}
</button>
);
}
That HTML-looking syntax is JSX. It compiles to regular JavaScript function calls. The <button> you write becomes React.createElement("button", ...) under the hood. You write JSX because it's readable. The browser gets JavaScript.
Components compose. You build small ones and assemble them into larger ones.
function UserCard({ user }) {
return (
<div className="card">
<Avatar src={user.avatarUrl} />
<UserInfo name={user.name} role={user.role} />
<Button label="View Profile" onClick={() => navigate(`/users/${user.id}`)} />
</div>
);
}
Avatar, UserInfo, and Button are all components. UserCard composes them. Your entire app is a tree of components all the way down.
State and Re-rendering
Components hold state. When state changes, React re-renders the component and its children to reflect the new data.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
useState returns the current value and a setter function. You call the setter, React schedules a re-render, the component runs again with the new value.
The mental model React enforces: UI is a function of state. Same state produces the same UI. You change the state; the UI catches up.
The Virtual DOM
React doesn't update the real DOM directly on every state change. It maintains a virtual DOM, a JavaScript representation of the actual DOM tree. When state changes, React:
- Runs your component functions with the new state
- Builds a new virtual DOM tree
- Diffs the new tree against the previous one (this is called reconciliation)
- Applies only the necessary changes to the real DOM
The virtual DOM got a lot of hype early on as the reason React was fast. Partially true. DOM operations are expensive; batching and minimizing them helps. The bigger benefit is the programming model. You describe the desired output. React handles the mutations. You stop thinking about "update this element" and start thinking about "what should the UI look like right now."
How React State Actually Works
React 16.8 introduced Hooks. Before Hooks, managing state and lifecycle required class components. Hooks let function components do everything classes could, with significantly less boilerplate.
The hooks you'll use constantly:
useState handles local component state (shown above).
useEffect handles side effects: fetching data, subscribing to events, anything that happens outside the render cycle.
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUser() {
const data = await fetch(`/api/users/${userId}`).then(r => r.json());
setUser(data);
setLoading(false);
}
fetchUser();
}, [userId]);
if (loading) return <p>Loading...</p>;
return <h1>{user.name}</h1>;
}
The dependency array at the end of useEffect controls when the effect re-runs. When those values change, the effect fires again. An empty array means run once on mount. No array at all means run after every render, which is almost always a mistake.
useContext accesses values from React Context without prop drilling.
useRef stores a mutable value that persists across renders without triggering re-renders. Use it for DOM references and values you need to track without causing updates.
useMemo and useCallback memoize expensive computations and keep function references stable across renders.
Passing Data Down
Data flows down in React through props. A parent passes data to a child via attributes.
function App() {
const [theme, setTheme] = useState('dark');
return <Dashboard theme={theme} onThemeChange={setTheme} />;
}
function Dashboard({ theme, onThemeChange }) {
return (
<div className={`dashboard ${theme}`}>
<button onClick={() => onThemeChange(theme === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
</div>
);
}
Props are read-only. A child component doesn't modify its props. If a child needs to communicate back upward, it calls a callback function the parent passed down.
One-directional data flow makes applications easier to trace. You know where data comes from. You know what changes it.
State Management Beyond useState
For simple apps, useState and props work fine. For larger apps with shared state across many components, you need something more structured.
React Context is built-in. Good for data that many components need: auth state, theme, locale. Gets expensive for high-frequency updates because any context change re-renders all consumers.
Zustand is small, fast, and has no boilerplate. Define a store, subscribe to it from any component.
import { create } from 'zustand';
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
function Counter() {
const { count, increment } = useStore();
return <button onClick={increment}>{count}</button>;
}
Redux Toolkit is the old standard, now with less boilerplate than classic Redux. Worth learning if you work in enterprise codebases; a lot of production React apps run on it.
TanStack Query handles server state specifically: data you fetch from an API. Caching, re-fetching, loading states, error states, all covered without you writing that logic yourself.
TypeScript and React
React and TypeScript work well together. You type your props, your state, and your hook return values. The compiler catches you passing the wrong thing to a component before you find out at runtime.
There's a whole debate about whether to bother with TypeScript at all. I've already written about it at length, go read the JavaScript vs TypeScript article if you want the full picture. For React specifically: type your props. It costs you five minutes of setup and saves hours of "why is this undefined" debugging.
React in the Ecosystem
React handles rendering and state. The ecosystem handles everything else.
React Router / TanStack Router for client-side routing. You define routes as components.
Next.js is the full framework built on React. It adds server-side rendering, static generation, API routes, and file-based routing. If you're building a production web app without a specific reason not to, Next.js is where most teams land.
Remix is server-first. Takes a different approach to data loading and mutations. Worth a look if Next.js feels like too much magic for your use case.
Vite is the modern build tool for React development. Instant dev server startup, fast hot module replacement, TypeScript and JSX compilation handled. We cover that tool in depth in the What is Vite article.
Getting Started
The fastest setup for a React project in 2026:
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev
You get a Vite-powered dev server (or use Bun if you want faster installs), React with TypeScript, and a working project under a minute. Don't use Create React App. It's deprecated and unmaintained. Vite replaced it years ago.
What React Is Not
React is a UI library. It handles rendering components and managing state changes. Routing, form validation, API calls, testing, animations, and bundling all come from separate packages.
That unbundled approach frustrated people coming from Rails or Django, where the framework makes all those decisions. It gives you flexibility at the cost of more decisions upfront. The ecosystem is mature enough that the decisions aren't hard, but know going in that "using React" means assembling several tools deliberately.
The Conclusion
React changed frontend development. The component model it popularized is now the baseline assumption across Vue, Angular, Svelte, and Solid. The hooks model for state and effects is how most of the industry structures UI logic.
The ecosystem moves fast. The job market values React heavily. Most frontend work you encounter in 2026 involves React or something heavily influenced by it.
Learn the component model. Understand state and re-rendering. Get comfortable with hooks. The rest is library choices on top of that foundation.
For the runtime side of JavaScript development outside the browser, the What is Node.JS article covers how JavaScript runs on servers and why that matters for your full-stack picture.