Frontend
Intermediate 17 min read Frontend

React Fundamentals

React builds UIs from declarative components. Understand JSX, props, state, hooks and the render/reconcile cycle so you can build maintainable interactive interfaces.

ReactJSXhooksuseStateuseEffectreconciliation
Introduction

What is this?

React is a library for building user interfaces from composable components. Components are functions that return JSX — a JavaScript syntax extension describing the UI as a tree of elements. React renders that tree, and when state or props change it re-runs components, diffs the new tree against the previous one, and applies the minimal DOM updates.

Motivation

Why do you need it?

  • The UI is declared from data, so the code shows what should render instead of how to mutate the DOM.
  • Components compose, so buttons, cards and pages are reusable and individually testable.
  • Unidirectional data flow — props down, events up — makes large UIs predictable.
  • A huge ecosystem of hooks and components means most needs already have a maintained solution.
  • Frameworks like Next.js and React Native reuse the same component model across web, server and mobile.
Think about it

Mental model

Imagine

A restaurant kitchen

Think of

React rendering

The menu describes each dish (components). When an order arrives, the kitchen cooks it from ingredients (state and props). If the order changes, the kitchen only replaces the dishes that actually changed — like React's reconciliation updating only the DOM nodes that differ.

Mechanics

How it works

  • A component function runs and returns JSX, which the JSX transform compiles into element objects.
  • useState returns the current value plus a setter; calling the setter schedules a re-render of that component.
  • On re-render, React builds the new element tree and reconciles it against the previous one.
  • The diff identifies changed props, state and keys, then updates only those DOM nodes in the commit phase.
  • Effects (useEffect) run after the browser paints, which is where subscriptions, timers and network reads belong.

The React render and commit cycle.

Component renders
JSX to elements
State update
Reconciliation
Commit
Effects
Reference

Key commands

npm create vite@latest my-app -- --template react

Scaffold a new React project with Vite.

Scaffolding project in my-app...
npm install

Install project dependencies.

npm run dev

Start the dev server with hot reload.

Local: http://localhost:5173/
npm run build

Create an optimized production build.

npm run lint

Run the ESLint config, including react-hooks rules.

npm run preview

Serve the production build locally to verify it.

Hands-on

Examples

A counter with state and an effect

A counter with state and an effect
import { useState, useEffect } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = "Count: " + count;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount((c) => c + 1)}>Increment</button>
</div>
);
}

useState(0) creates the count state. Each click calls the setter with a function, which updates count and schedules a re-render. useEffect synchronizes the document title whenever count changes, and its dependency array keeps the effect scoped to exactly that state.

Real world

In production

  • Interactive applications such as dashboards, editors and commerce flows where DOM manipulation would be unmanageable.
  • React serves as the rendering layer inside Next.js, Remix and other meta-frameworks for SSR and static output.
  • Design-system teams ship component libraries that other products consume as a package.
  • React Native reuses component thinking for iOS and Android apps.
Guidelines

Best practices

  • Keep components pure: same props and state always produce the same output, with side effects moved into effects or handlers.
  • Use keys that are stable and unique; prefer data ids over array indexes.
  • Lift state to the lowest common ancestor so sibling components can share it.
  • Extract repeated logic into custom hooks with clear, typed signatures.
  • Set up eslint-plugin-react-hooks so dependency and hook-order mistakes fail CI.
Watch out

Common mistakes

  • Mutating state in place (state.push) so React misses the change and nothing re-renders.
  • Using array indexes as keys, which corrupts list state during reordering.
  • Omitting dependencies from useEffect and reading stale closures.
  • Putting every shared value in Context and re-rendering the whole tree on every change.
Root cause analysis

Common issues

Error
Too many re-renders. React limits the number of renders
Root cause

A state update is triggered during render instead of in an event handler or effect.

Fix

Wrap the update in a click handler or effect rather than calling the setter directly in the render body.

Error
Each child in a list should have a unique key
Root cause

List items lack a key or reuse the array index.

Fix

Assign a stable key such as item.id to the top-level element of each item.

Error
Effects run on every render
Root cause

The dependency array is missing or includes unstable values.

Fix

Provide a dependency array and memoize object/function props with useMemo and useCallback.

When things break

Debugging tips

  • Install the React DevTools browser extension to inspect the component tree, props and hook values.
  • Run StrictMode in development to surface double-rendering bugs and unsafe effects.
  • Trace re-renders with the Profiler tab to find components updating on every parent render.
  • Log state transitions in the setter or event handler, not inside the render body, to avoid infinite loops.
Interviews

Interview checkpoint

Practice

Hands-on lab

Build a Task Tracker with Hooks
35 min · intermediate
In progress
Objectives
  • Scaffold a React project with Vite
  • Manage a list with useState
  • Lift state and pass callbacks as props
  • Render lists with stable keys

Build a Task Tracker with Hooks

35 min · intermediate

0/5 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/3
1

Which hook returns a value and a function to update it?

2

Mutating state with push() reliably triggers a re-render.

3

What is the recommended way to give list items a stable identity?

Quick reference

Cheat sheet

Hooks
useState(0)Local state with a setter
useEffect(fn, deps)Run effects after paint
useContext(Ctx)Read from a provider
useReducer(reducer, init)State with update logic
useMemo / useCallbackMemoize values and callbacks
JSX essentials
{expression}Embed a JavaScript value
onClick={handleClick}Attach an event handler
classNameHTML class, renamed in JSX
items.map((i) => <li key={i.id}>)Render a list
Go deeper

Official documentation