Course topics

By WebNest Studio Engineering Team

React Tutorial

Introduction to React Hooks

Hooks are special functions, all starting with the word "use", that let function components tap into React features like state, side effects, and context without writing a class. Before hooks were introduced, only class components could hold state or run lifecycle logic; hooks brought that same power to plain functions, which is why modern React code is written almost entirely with function components.

Common built-in hooks include useState for local state, useEffect for side effects, useContext for reading context, useRef for mutable values that persist without causing re-renders, useMemo and useCallback for memoization, and useReducer for more complex state logic. React also lets you build your own custom hooks by combining these building blocks.

Why it matters

Hooks are how function components get state, side effects and access to React's features. They come with two rules that are not optional: React identifies each hook by the order in which it is called, so breaking the rules produces state that silently belongs to the wrong variable.

The Rules of Hooks

Hooks work reliably only if they are called in a very specific, consistent way, because React matches up hook calls between renders purely by the order in which they were called — not by name.

  • Only call hooks at the top level. Never call a hook inside a loop, a conditional, or a nested function — doing so can change how many hooks run, or in what order, between renders.
  • Only call hooks from React functions. Call them from function components or from other custom hooks, never from plain JavaScript functions or class components.
  • Call them in the same order every render. Because React relies on call order to associate each hook with its stored state, conditionally skipping a hook call would misalign every hook that comes after it.

Why Hooks Replaced Class Lifecycle Methods

Class components spread related logic across separate lifecycle methods (componentDidMount, componentDidUpdate, componentWillUnmount), which often forced you to duplicate the same logic in multiple places. Hooks let you group related logic together in one place regardless of when it runs, and they make it far easier to extract and reuse stateful logic across components through custom hooks — something class components could not do cleanly.

ESLint Enforcement of Hook Rules

Because breaking the Rules of Hooks can cause subtle, hard-to-trace bugs, most React projects install the eslint-plugin-react-hooks package, which statically flags hooks called conditionally, inside loops, or from non-component functions before the code ever runs.

Example

Correct top-level hook usage versus an invalid conditional hook call

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

// Correct: hooks always called at the top level, in the same order every render.
function UserStatus({ userId }) {
  const [isOnline, setIsOnline] = useState(false);

  useEffect(() => {
    setIsOnline(userId % 2 === 0); // pretend even IDs are "online" for this example
  }, [userId]);

  return <p>{isOnline ? 'Online' : 'Offline'}</p>;
}

// Incorrect (do not do this): calling useState inside a condition
// function BrokenComponent({ showExtra }) {
//   if (showExtra) {
//     const [extra, setExtra] = useState(0); // breaks the Rules of Hooks
//   }
//   return <div />;
// }

export default function App() {
  return <UserStatus userId={4} />;
}
Output
Renders "Online" because userId (4) is even, per the effect's logic; the commented-out BrokenComponent illustrates the invalid pattern of calling useState conditionally, which React would reject with a "Rendered more hooks than during the previous render" style error if it were actually run under changing conditions.

Common Mistakes

  • Calling a hook inside an if statement, loop, or nested helper function instead of at the top level of the component.
  • Calling hooks from a regular JavaScript function or a class component instead of a function component or another custom hook.
  • Assuming hook order does not matter because hooks are "just functions" — React actually depends entirely on consistent call order across renders.
  • Ignoring eslint-plugin-react-hooks warnings instead of treating them as real bugs waiting to happen.

Exercise

Do this in src/App.jsx of a Vite + React project. The component below breaks the rules of hooks by calling useState inside a condition. Fix it so that every hook is called at the top level on every render, while keeping the behaviour: the detail text is shown only when showDetails is true.

Expected result: the component works with showDetails true or false, and the React hooks lint rule reports no error.

JavaScript · starter code
import { useState } from "react";

function Profile({ showDetails }) {
  const [name] = useState("Asha");

  if (showDetails) {
    const [bio] = useState("Developer from Pune");
    return <p>{name}: {bio}</p>;
  }

  return <p>{name}</p>;
}

export default function App() {
  return <Profile showDetails={true} />;
}
Show hints
  • Move both useState calls to the top of the function, before any condition.
  • Put the condition in what is rendered, not around the hook.
Show solution
JavaScript · solution
import { useState } from "react";

function Profile({ showDetails }) {
  const [name] = useState("Asha");
  const [bio] = useState("Developer from Pune");

  if (showDetails) {
    return <p>{name}: {bio}</p>;
  }

  return <p>{name}</p>;
}

export default function App() {
  return <Profile showDetails={true} />;
}

Quick quiz

1. Where may hooks be called?

  • A. Anywhere in a JavaScript file
  • B. Inside loops and conditions
  • C. In event handlers
  • D. At the top level of a function component or of a custom hook
Show answer

D. They must not be called inside conditions, loops or nested functions.

2. Why must hooks be called in the same order on every render?

  • A. React matches each hook call to its stored state by the order of the calls
  • B. It is only a style rule
  • C. To make the code faster
  • D. Because of JavaScript hoisting
Show answer

A. A hook skipped by a condition shifts every hook after it to the wrong state.

3. How are the rules of hooks usually enforced?

  • A. By the browser
  • B. By the ESLint plugin eslint-plugin-react-hooks
  • C. By TypeScript
  • D. They are not enforced
Show answer

B. It reports hooks called conditionally and missing effect dependencies.

Interview questions

What are the rules of hooks?

Show answer

First, call hooks only at the top level of a component or custom hook: never inside conditions, loops, nested functions or after an early return. Second, call hooks only from React function components or from custom hooks, not from ordinary JavaScript functions. React relies on hooks being called in the same order on every render to associate each call with its state.

Why were hooks introduced?

Show answer

Before hooks, state and lifecycle logic required class components. Related logic was split across lifecycle methods, unrelated logic was mixed within one method, and sharing stateful logic between components needed awkward patterns such as higher-order components and render props. Hooks let function components hold state and side effects, keep related logic together, and allow it to be extracted into reusable custom hooks.

Key Points to Remember

  • Hooks are functions starting with "use" that let function components use state, effects, context, and more.
  • Hooks must be called only at the top level of a component or custom hook — never inside conditionals, loops, or nested functions.
  • React matches hooks between renders by call order, so that order must stay identical on every render.
  • Hooks replaced scattered class lifecycle methods with reusable, composable logic, including custom hooks.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Shows a live preview of plain HTML, CSS and JavaScript. JSX needs a React project on your computer. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

These examples need a project environment on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering