Ad – 728Γ—90
⚑ Frameworks

React – The Most Popular JavaScript UI Framework

React is a declarative, component-based JavaScript library for building user interfaces. Created by Facebook (Meta) in 2013, it has become the most widely used front-end library in the world. React's key innovation is the virtual DOM β€” an in-memory representation of the UI that makes updates fast and predictable.

⏱️ 25 min read 🎯 Advanced πŸ“… Updated 2026

What Is React?

React is not a full framework β€” it is a view library. It handles rendering the UI and reacting to state changes. For routing, data fetching, and state management you add other libraries. This composability makes it flexible but requires more architectural decisions than opinionated frameworks like Angular.

React's core ideas:

  • Declarative β€” describe what the UI should look like for a given state; React figures out how to update the DOM.
  • Component-based β€” build encapsulated components that manage their own state, compose them into complex UIs.
  • Learn once, write anywhere β€” React Native reuses the same knowledge for iOS/Android apps.

JSX Syntax

JSX is a syntax extension that lets you write HTML-like markup inside JavaScript. Babel compiles it to React.createElement() calls:

JavaScript
// JSX β€” what you write
const element = <h1 className="title">Hello, React!</h1>;

// Compiled β€” what Babel produces
const element = React.createElement('h1', { className: 'title' }, 'Hello, React!');

// JSX rules:
// 1. Return a single root element (or use <Fragment> / <></>)
// 2. All tags must be closed: <img />, <br />
// 3. Use className instead of class
// 4. JavaScript expressions in curly braces {}
const name = 'Alice';
const greeting = (
  <div>
    <h1>Hello, {name}!</h1>
    <p>Today is {new Date().toDateString()}</p>
    <p>2 + 2 = {2 + 2}</p>
  </div>
);

// Fragment β€” wraps multiple elements without adding a DOM node
const items = (
  <>
    <li>Item 1</li>
    <li>Item 2</li>
  </>
);

Functional Components

A React component is a JavaScript function that returns JSX. Functions are the modern standard (class components are legacy):

JavaScript
// Simplest component β€” no state, no props
function Hello() {
  return <h1>Hello, World!</h1>;
}

// Component with props (read-only data passed from parent)
function UserCard({ name, email, avatar }) {
  return (
    <div className="user-card">
      <img src={avatar} alt={name} />
      <h2>{name}</h2>
      <p>{email}</p>
    </div>
  );
}

// Using the component β€” looks like an HTML tag
function App() {
  return (
    <div>
      <Hello />
      <UserCard
        name="Alice"
        email="alice@example.com"
        avatar="/alice.jpg"
      />
    </div>
  );
}

// Render to DOM (React 18+)
import { createRoot } from 'react-dom/client';
createRoot(document.getElementById('root')).render(<App />);
πŸ’‘
Props are read-only

Never modify props directly β€” doing so violates React's data flow and causes bugs. If a child needs to update data owned by the parent, the parent passes a callback function as a prop, and the child calls it.

State with useState

State is data that can change over time. When state updates, React re-renders the component:

JavaScript
import { useState } from 'react';

function Counter() {
  // useState returns [currentValue, setterFunction]
  const [count, setCount] = useState(0);  // 0 is the initial value

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}

// State with objects
function UserForm() {
  const [user, setUser] = useState({ name: '', email: '' });

  const handleChange = (e) => {
    // Always spread existing state to avoid losing other fields
    setUser(prev => ({ ...prev, [e.target.name]: e.target.value }));
  };

  return (
    <form>
      <input name="name" value={user.name} onChange={handleChange} />
      <input name="email" value={user.email} onChange={handleChange} />
      <p>Preview: {user.name} β€” {user.email}</p>
    </form>
  );
}
β–Ά Behaviour
Click + β†’ Count: 1 β†’ Count: 2 β†’ Count: 3
Click Reset β†’ Count: 0

Side Effects with useEffect

useEffect runs code after render β€” for data fetching, subscriptions, DOM manipulation, and timers:

JavaScript
import { useState, useEffect } from 'react';

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  // [] dependency array β†’ run once on mount (componentDidMount equivalent)
  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(r => r.json())
      .then(data => { setUsers(data); setLoading(false); })
      .catch(err => { setError(err.message); setLoading(false); });
  }, []);

  // [id] dependency array β†’ run whenever id changes
  // No array β†’ run after EVERY render (usually a bug)

  // Cleanup β€” return a function to run before next effect or unmount
  useEffect(() => {
    const timer = setInterval(() => console.log('tick'), 1000);
    return () => clearInterval(timer); // cleanup on unmount
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error)   return <p>Error: {error}</p>;

  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

Lists and Conditional Rendering

JavaScript
// Rendering lists with .map() β€” key prop is required
function TodoList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id} className={item.done ? 'done' : ''}>
          {item.text}
        </li>
      ))}
    </ul>
  );
}

// Conditional rendering β€” && operator
function Notification({ message }) {
  return (
    <div>
      {message && <p className="notification">{message}</p>}
    </div>
  );
}

// Conditional rendering β€” ternary
function AuthButton({ isLoggedIn }) {
  return (
    <button>{isLoggedIn ? 'Log Out' : 'Log In'}</button>
  );
}

// Early return pattern
function Profile({ user }) {
  if (!user) return <p>Please log in</p>;
  return <h1>Welcome, {user.name}!</h1>;
}
⚠️
The key prop must be unique and stable

React uses key to track list items during re-renders. Never use array index as key when items can be reordered or deleted β€” use a stable unique ID from your data. Unstable keys cause subtle rendering bugs and hurt performance.

React Ecosystem Overview

CategoryLibraryPurpose
RoutingReact Router v6Client-side navigation, nested routes
State (global)ZustandLightweight, simple global state
State (global)Redux ToolkitPredictable state container, DevTools
Data fetchingTanStack QueryServer state, caching, re-fetching
FormsReact Hook FormPerformant forms with minimal re-renders
StylingTailwind CSS / styled-componentsUtility CSS or CSS-in-JS
Meta-frameworkNext.jsSSR, SSG, API routes, file-based routing
MobileReact NativeiOS + Android apps with React

πŸ‹οΈ Practical Exercise

Build a colour-picker component in React (Vite or CodeSandbox):

  1. Create a ColorPicker component with a state variable for the selected colour.
  2. Render 5 colour buttons. Clicking one updates the state.
  3. Display a large coloured preview box below the buttons.
  4. Show the hex value of the selected colour as text.
  5. Pass the selected colour back to the parent via a callback prop.

πŸ”₯ Challenge Exercise

Build a fully functional CRUD app: a "Contact Book" that lets you add, view, edit, and delete contacts. Use useState for the contacts array, a separate form component with controlled inputs, a contact list component, and a detail view. Persist contacts to localStorage using useEffect. Add a search filter using derived state (filter the contacts array based on an input value β€” no extra state needed).

Summary

πŸ“‹ Summary

  • React is a declarative, component-based view library powered by a virtual DOM.
  • JSX is compiled to React.createElement() β€” it's JavaScript, not HTML.
  • Functional components are plain functions that return JSX.
  • Props pass read-only data from parent to child; never mutate props.
  • useState manages local state; calling the setter triggers a re-render.
  • useEffect runs side effects after render; the dependency array controls when it runs.
  • Use .map() for lists with a stable unique key prop.
  • Use && or ternary for conditional rendering.

Interview Questions

  • What is the virtual DOM and why does it improve performance?
  • What is the difference between props and state?
  • When would you use useEffect with an empty dependency array vs a non-empty one?
  • Why must list items have a key prop? What's wrong with using array index?
  • What is the difference between controlled and uncontrolled components?

Frequently Asked Questions

What is the difference between Create React App and Vite? +

Create React App (CRA) is the original scaffold tool that uses Webpack under the hood. It's slow to start and build. Vite uses native ES modules and esbuild, making dev startup near-instant. For new projects in 2026, use Vite or Next.js β€” CRA is no longer actively maintained.

What is a controlled vs uncontrolled component? +

A controlled component has its value driven by React state: value={state} + onChange handler. React owns the data. An uncontrolled component manages its own value in the DOM; you read it via a ref. Controlled components are preferred for validation and dynamic UIs. Use uncontrolled components for simple file inputs or when integrating with non-React code.

Why does React re-render and how can I prevent unnecessary re-renders? +

React re-renders a component when its state or props change. To prevent unnecessary child re-renders: wrap the component in React.memo() (skips render if props didn't change), use useCallback to memoize callback props, and useMemo to memoize expensive computations. Premature optimization is a trap β€” profile first, memoize only where there's a measurable benefit.

Ad – 336Γ—280