LearnContact
Lesson 2718 min read

React Hooks Introduction

Discover what Hooks are, why React introduced them in version 16.8, and the strict rules you must follow when using them.

Introduction

For the first several years of React's life, if you wanted a component to hold state or run code in response to being mounted, updated, or unmounted, you had to write it as a class component, using this.state, this.setState, and lifecycle methods like componentDidMount. This worked, but classes brought real friction: confusing this bindings, logic scattered across multiple lifecycle methods, and stateful logic that was hard to reuse between components.

In React 16.8 (released in 2019), the React team introduced Hooks — plain functions that let function components "hook into" React features like state and lifecycle behavior, without ever writing a class. Hooks quickly became the standard, recommended way to write React, and nearly all modern React code you will encounter uses them. This lesson introduces what Hooks are, why they exist, and the strict rules that keep them working correctly.

What You Will Learn
  • What a Hook actually is under the hood.
  • Why Hooks were introduced to replace class-based patterns.
  • The two Rules of Hooks and why they exist.
  • What happens when the rules are broken.
  • A preview of the core built-in Hooks you will learn next.

What Are Hooks?

A Hook is simply a function — one that gives a function component access to React features that used to require a class. useState lets a function component hold state. useEffect lets it run side effects. useRef lets it hold a mutable value across renders. Every Hook name starts with "use", which is both a naming convention and a signal to React and to linting tools that a function follows the special Rules of Hooks.

A Function Component "Hooking Into" State
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}

Before Hooks existed, the exact same behavior required a class component with a constructor, this.state, and this.setState. Hooks let you achieve it with a single line inside a plain function.

Just Functions

Hooks are ordinary JavaScript functions provided by React (or written yourself as custom hooks).

Named "use..."

Every Hook, built-in or custom, starts with the word "use" by convention.

Access React Internals

Hooks let function components tap into state, context, refs, and lifecycle-like behavior.

Reusable Logic

Custom hooks let you extract and share stateful logic between components.

Why Hooks Were Introduced

Class components were not broken, but they came with several persistent pain points that the React team set out to solve with Hooks.

Class Components (Before Hooks)

  • Confusing `this` bindings — methods often needed manual `.bind(this)`.
  • Related logic split across componentDidMount, componentDidUpdate, componentWillUnmount.
  • Stateful logic was hard to reuse — required patterns like higher-order components or render props.
  • More boilerplate: constructors, super(props), and verbose class syntax.

Function Components (With Hooks)

  • No `this` at all — just plain variables and closures.
  • Related logic can live together in a single useEffect call.
  • Custom hooks make sharing stateful logic between components simple.
  • Less boilerplate — components are just functions.
The Core Motivation

React's team wanted a way to use state and other React features without writing a class, and a way to reuse stateful logic between components without restructuring the component tree. Hooks solve both problems at once.

The Rules of Hooks

Hooks look like normal function calls, but React relies on them being called in the exact same order on every single render, so it can correctly match each Hook call to its corresponding internal state. This is why Hooks come with two strict rules that you must always follow.

The Two Rules

  • Only call Hooks at the top level. Never call a Hook inside a loop, a condition, or a nested function — always call them in the same order, every render.
  • Only call Hooks from React function components or from custom Hooks. Never call a Hook from a regular JavaScript function, a class component, or outside of React entirely.
Breaking the Rules (Do Not Do This)
function Profile({ isLoggedIn }) {
  // ❌ Hook called conditionally — breaks the call order
  if (isLoggedIn) {
    const [name, setName] = useState("");
  }

  // ❌ Hook called inside a loop
  for (let i = 0; i < 3; i++) {
    const [item, setItem] = useState(null);
  }

  return <div>...</div>;
}
Following the Rules
function Profile({ isLoggedIn }) {
  // ✅ Always called, in the same order, every render
  const [name, setName] = useState("");

  // The condition goes inside the logic, not around the Hook call
  if (isLoggedIn) {
    console.log(`Welcome, ${name}`);
  }

  return <div>{isLoggedIn ? name : "Guest"}</div>;
}

Why the Rules Matter

React does not track Hooks by name — it tracks them by call order. Internally, each component keeps an ordered list of Hook "slots," and every render, React walks through that list matching the first useState call to the first slot, the second call to the second slot, and so on. If a Hook is skipped conditionally on some renders but not others, that ordering breaks, and React can attach the wrong state to the wrong Hook — or throw an error outright.

What Happens When Order Shifts
Render 1: useState() -> slot 1,  useState() -> slot 2
Render 2 (if skipped):  useState() -> slot 1  (only one call!)

React expected 2 Hook calls but found 1 —
state becomes mismatched or React throws:
"Rendered fewer hooks than expected."
ESLint Catches This For You

The official eslint-plugin-react-hooks package (enabled by default in most React project templates) will flag Rules of Hooks violations immediately as you type, so you rarely have to track these bugs down manually.

A Preview of Built-In Hooks

React ships with a set of built-in Hooks covering the most common needs — state, side effects, references, performance, and more. The next several lessons walk through each of these in depth.

useState

Adds a piece of state to a function component and a way to update it.

useEffect

Runs side effects — data fetching, subscriptions, timers — after render.

useRef

Holds a mutable value or a reference to a DOM element across renders, without causing re-renders.

useMemo

Memoizes an expensive calculation so it is not recomputed on every render.

useCallback

Memoizes a function definition so it keeps the same identity between renders.

useContext

Reads a value from React Context without wrapping components in a Consumer.

Common Mistakes

Avoid These Mistakes
  • Calling a Hook inside an if statement, a for loop, or a nested helper function — always call Hooks at the top level of the component.
  • Calling a Hook from a plain JavaScript utility function instead of a component or a custom Hook.
  • Naming a custom function that calls Hooks without the "use" prefix, which hides its special behavior from linting tools.
  • Assuming Hooks are only for state — useEffect, useRef, and others solve very different problems.

Best Practices

  • Always enable eslint-plugin-react-hooks in your project so rule violations are caught immediately.
  • Keep conditions and loops inside your Hook calls' logic, never wrapped around the Hook call itself.
  • Name every custom Hook starting with "use", even if it feels like a simple helper.
  • Extract repeated stateful logic into a custom Hook rather than copy-pasting it between components.
  • Read each Hook's documentation on react.dev before using it for the first time — subtle behaviors like dependency arrays matter.

Frequently Asked Questions

Can I still use class components in React?

Yes, class components still work and React has no plans to remove them, but Hooks are the recommended, modern approach, and most new code and documentation assumes function components with Hooks.

What exactly is a "custom Hook"?

A custom Hook is simply a JavaScript function whose name starts with "use" and that calls other Hooks inside it. It lets you extract and reuse stateful logic across multiple components.

Why must Hook names start with "use"?

It is a convention that both developers and tools rely on. ESLint's react-hooks plugin uses the "use" prefix to know which functions to check against the Rules of Hooks.

Can I call a Hook inside an event handler, like onClick?

No. Hooks must be called during the component's render, at the top level — not inside callbacks, event handlers, or effects. You can call functions like setCount (returned by a Hook) inside a handler, just not the Hook itself.

Do Hooks work in React Native as well?

Yes. Hooks are part of React core, not React DOM specifically, so useState, useEffect, and the rest work identically in React Native.

Key Takeaways

  • Hooks are functions that let function components use state, effects, and more, without writing a class.
  • They were introduced in React 16.8 to remove `this` confusion and make stateful logic easier to reuse.
  • Rule 1: only call Hooks at the top level — never inside loops, conditions, or nested functions.
  • Rule 2: only call Hooks from React function components or from other custom Hooks.
  • React relies on consistent call order across renders to correctly match state to each Hook call.

Summary

Hooks transformed how React components are written, replacing verbose class-based patterns with simple functions that plug directly into React's internals. The two Rules of Hooks — top-level calls only, and calls only from components or custom Hooks — exist to protect the consistent call order React depends on to track state correctly.

With this foundation in place, you are ready to start learning the built-in Hooks one at a time, beginning with the one you will use constantly: useState.

Lesson 27 Completed
  • You understand what a Hook is and why it exists.
  • You can explain why Hooks replaced class-based lifecycle patterns.
  • You know both Rules of Hooks and why they matter.
  • You have a roadmap of the built-in Hooks coming up next.
Next Lesson →

useState Hook