Skip to main content

What is React and why is it needed?

React is an open-source JavaScript library for building user interfaces by composing reusable components.

Theory

TL;DR

  • React is like a restaurant kitchen: each chef (component) handles one dish independently, and the head chef (React) updates only the items on the plate that changed, not the whole order.
  • Main difference: declarative (describe the UI you want) vs. imperative (manually tell the DOM what to change, step by step).
  • Virtual DOM sits between your code and the real DOM, batching and minimizing actual browser updates.
  • Use React when your app has dynamic UIs with frequent state changes. Skip it for static pages.

Quick example

jsx
import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // state triggers re-render return ( <div> <p>Count: {count}</p> {/* UI described as a function of state */} <button onClick={() => setCount(count + 1)}>+1</button> </div> ); }

The useState hook stores count between renders. When setCount fires, React diffs the new virtual DOM against the old one and updates only the <p> text node. No document.querySelector. No manual textContent assignment.

Declarative vs. imperative

React's declarative model says: "when count is 5, show this." You define the outcome, not the steps. Vanilla JS forces you to find the DOM node, update the text, and handle every edge case by hand. That is three times more code and three times more places for bugs to hide.

Once you ship a feature with 20 components that all read the same state, you really feel the difference.

Virtual DOM: why it exists

The browser DOM is slow for frequent updates. React keeps a lightweight JavaScript copy of the DOM (the virtual DOM). On each state change, React runs a diff algorithm called reconciliation, comparing the new virtual DOM snapshot to the previous one. Only the changed nodes get written to the real DOM.

React 18 added the Fiber architecture, which breaks rendering work into small units and schedules them across browser frames with priority queues. User input goes first. Background data fetches can wait.

When to use React

  • Dynamic lists and forms with add/delete/filter: React.
  • Static marketing or brochure page: plain HTML/CSS is enough.
  • Full-stack app with server rendering: Next.js (React with SSR under the hood).
  • Mobile apps: React Native, same JSX syntax, native output.
  • Simple interactivity on a static page: vanilla JS or HTMX will do.

Common mistakes

Mutating state directly:

jsx
// Wrong: React sees the same array reference, skips re-render const [todos, setTodos] = useState([]); todos.push(newTodo); setTodos(todos); // Correct: new reference triggers the diff setTodos([...todos, newTodo]);

Using array index as key:

jsx
// Wrong: breaks reconciliation on reorder {items.map((item, index) => <li key={index}>{item.text}</li>)} // Correct: stable ID {items.map(item => <li key={item.id}>{item.text}</li>)}

Missing cleanup in useEffect:

jsx
useEffect(() => { const id = setInterval(fetchData, 5000); return () => clearInterval(id); // without this: memory leak }, []);

Stale closure in useEffect:

jsx
// count inside the interval is always 0 useEffect(() => { const id = setInterval(() => console.log(count), 1000); return () => clearInterval(id); }, []); // empty deps capture count=0 forever // Fix: add count to deps, or use a ref

Real-world usage

  • Netflix: reusable player components, virtual DOM keeps scrubbing smooth.
  • Facebook Newsfeed: React Fiber handles updates for billions of users.
  • Airbnb: dynamic search filters built with hooks.
  • Shopify storefronts: Next.js (React with SSR) for e-commerce pages.
  • Instagram: React Native shares UI logic with the web app.

Follow-up questions

Q: What is the virtual DOM and why does React use it?
A: A JavaScript object tree that mirrors the real DOM. React diffs it on each update to find the minimal set of real DOM changes. Fewer DOM writes means a faster UI.

Q: What is JSX?
A: Syntactic sugar that compiles to React.createElement('div', null, 'text') via Babel. It is not HTML and not required, but it makes component trees much easier to read.

Q: What is the difference between useState and useReducer?
A: useState works for isolated, simple values. useReducer fits complex state logic where multiple sub-values relate to each other, or where the next state depends on the previous one.

Q: Why do immutable updates matter?
A: React checks state equality with ===. Mutate an object in place and the reference stays the same, so React sees no change and skips the re-render. Immutable updates create new references, which triggers the diff correctly.

Q: What did React 18 concurrent mode add?
A: useTransition lets you mark non-urgent updates so React can pause them and handle user input first. The UI stays responsive during heavy data fetches instead of freezing.

Examples

Basic: counter component

jsx
import { useState } from 'react'; import { createRoot } from 'react-dom/client'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>+1</button> </div> ); } createRoot(document.getElementById('root')).render(<Counter />); // Clicking '+1' updates only the <p> text node, not the whole DOM

State lives in the component. When setCount is called, React re-renders Counter, diffs the output, and patches the single changed text node in the real DOM.

Intermediate: todo list with immutable state updates

jsx
import { useState } from 'react'; function TodoList() { const [todos, setTodos] = useState([ { id: 1, text: 'Learn React', done: false } ]); const toggleTodo = (id) => { setTodos(todos.map(todo => todo.id === id ? { ...todo, done: !todo.done } : todo )); // spread creates a new object - React detects the change }; return ( <ul> {todos.map(todo => ( <li key={todo.id} onClick={() => toggleTodo(todo.id)}> {todo.text} {todo.done ? '(done)' : ''} </li> ))} </ul> ); }

Clicking a todo runs toggleTodo. The spread operator creates a new object for the toggled item and a new array for todos. React's diff picks up the changed <li> and updates only that node.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?