Understanding Hooks

By Syncfusion®, Inc. · Last updated

What hooks are, their benefits and rules, when to use them, the five groups of built-in hooks, a tour of useState, useEffect, useRef, useContext, useReducer, useMemo and useCallback, and how to choose the right one.

Introduction to Hooks

A hook is a special React function that gives a component an extra power, such as remembering a value or running code after the screen updates. Every hook's name starts with use.

You have already used one hook: useState. It gives a component the power to remember a value. React has more hooks, and each one gives a different power.

Real-World Example

A bookshop's book page must remember how many copies the user selected. A normal variable is reset every time the component runs again, so the number is lost.

The component calls the hook useState(1). React keeps the number between renders, and the page shows the new quantity each time the user clicks +.

A hook is a function whose name starts with use. You call it inside a component to give the component a new power.

Benefits of Hooks

Before hooks, many React powers were only available in class components, which were longer and harder to read. Hooks bring the same powers to normal function components.

  • Shorter code — Function components with hooks need less code than classes.
  • Easier to read — Code for one job sits together, not split across many places.
  • Reusable logic — You can move hook code into your own hook and share it. You will learn this in the next lesson.
  • Easier to test — Small functions are easier to check than big classes.

Rules of Hooks

Hooks must follow two rules. If you break them, React can mix up your hooks and show wrong data.

Rule 1: Call Hooks Only at the Top Level

Call hooks at the top of your component. Do not call them inside an if, a loop, or a nested function.

// Wrong: the hook is inside an if
if (isLoggedIn) {
  const [name, setName] = useState("");
}

// Right: the hook is at the top. Use the if later.
const [name, setName] = useState("");
if (isLoggedIn) {
  // use name here
}

React remembers hooks by their order: the first useState, the second useState, and so on. If a hook is inside an if, it may be skipped on some renders. Then the order changes, and React gives the wrong value to the wrong hook.

Rule 2: Call Hooks Only from React Functions

Call hooks only inside:

  • a component (a function whose name starts with a capital letter), or
  • a custom hook (a function whose name starts with use).

Do not call hooks inside a normal JavaScript function.

Easy way to remember: hooks go at the top of a component or custom hook. Nowhere else.

Built-in Hook Categories

React's built-in hooks fall into five groups, based on what they do.

Five groups of hooks: State (useState, useReducer), Effect (useEffect), Reference (useRef), Context (useContext), Performance (useMemo, useCallback)

State useState useReducer

Effect useEffect

Reference useRef

Context useContext

Performance useMemo useCallback

The five groups of built-in hooks, and the common hooks in each group.

State Hooks

State hooks let a component remember data that changes the screen. They are useState and useReducer.

Effect Hooks

Effect hooks run code after React updates the screen, for work outside React. Examples: loading data, starting a timer, or changing the page title. The main one is useEffect.

Reference Hooks

Reference hooks remember a value without updating the screen when it changes. They can also hold a link to a real element on the page. The main one is useRef.

Context Hooks

Context hooks read data that is shared by many components, without passing props through every level. The main one is useContext.

Performance Hooks

Performance hooks help React skip work that is not needed, so the app stays fast. They are useMemo and useCallback.

Common Hooks Overview

This section shows each common hook in a short example.

useState

useState remembers a value. When you change it with the set function, React updates the screen. You learned it in the State lesson.

useState: count is 0, setCount(1) saves 1, React re-renders, the screen shows 1

count = 0 the value now

setCount(1) save a new value

Screen shows 1 React re-renders

useState keeps a value. Calling the set function saves a new value, and React shows it.

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

useEffect

useEffect runs code after React shows the component on the screen. You give it a function, and a list of values to watch, called the dependency array.

useEffect runs after React renders and updates the screen

1. Render run the component

2. Update screen show the new TSX

3. Run effect your useEffect code

Effects run last: after React renders and updates the screen.

The console shows a message when the page first appears. Each click shows a new message, because count is in the list [count]. Lesson 13 explains effects in detail.

useRef

useRef gives you a box called a ref, with one property: current. You can put any value in ref.current. Changing it does not update the screen.

useRef: ref.current points to the real input element. Changing ref.current does not re-render

inputRef current: ●

points to

<input /> the real element on the page Changing ref.current does not update the screen.

A ref is a box with one property, current. Here it holds a link to the input element.

A common use is to hold a link to a real element, for example to move the cursor into an input box.

ref={inputRef} connects the ref to the input. After that, inputRef.current is the real input element. ?. means: call focus() only if the element is there.

useContext

useContext reads a value that a parent shares with all components below it. You do not need to pass the value as a prop through every level.

useContext: the Provider shares the theme. ThemedBadge reads it directly, Toolbar in the middle passes nothing

Provider value="dark" shares the theme

Toolbar passes nothing

ThemedBadge useContext → "dark"

The value goes straight from the Provider to the component that reads it. The middle component is skipped.

App shares theme with <ThemeContext.Provider value={theme}>. ThemedBadge reads it with useContext(ThemeContext). Toolbar, in the middle, does not pass any props.

useReducer

useReducer is like useState, but for state with many different changes. You write all the changes in one function, called a reducer. Then you call dispatch with an action that names the change.

useReducer: a button dispatches an action, the reducer works out the new count, the screen updates

dispatch { type: "add" }

cartReducer (count, action) → new count

count = 1 screen updates

Buttons only name the change. The reducer decides the new value.

Look at this line:

const [count, dispatch] = useReducer(cartReducer, 0);
  • cartReducer is the function that decides each change.
  • 0 is the starting value.
  • dispatch({ type: "add" }) asks the reducer to do the "add" change.

All the cart rules live in one place: cartReducer.

useMemo

useMemo remembers the result of a calculation. It does the calculation again only when its inputs change. This saves time when the calculation is slow.

useMemo: if search changed, calculate again. If not, reuse the saved result

Render is search new?

yes

Filter the books again slow work, then save the result

no

Reuse the saved result no slow work

useMemo does the slow work only when its inputs change.

Type in the box. The console shows "Filtering..." each time. Now click Like the shop. The page updates, but the console shows nothing new. useMemo reused the old result, because search did not change.

useCallback

useCallback remembers a function, so the same function is used on every render. This matters when you pass the function to a child that only re-renders when its props change.

useCallback: render 1 and render 2 both use the same handleBuy function

Render 1

Render 2

handleBuy the same function

With useCallback, every render gets the same function, not a new one.

const handleBuy = useCallback((title: string) => {
  console.log("Buying " + title);
}, []); // the same function every render

Without useCallback, a new handleBuy function is made on every render. You will use it in the performance lesson. For now, remember: useMemo remembers a value, useCallback remembers a function.

Choosing the Appropriate Hook

When you are not sure which hook to use, ask these questions in order:

  1. Does the screen need to change when this value changes? Use useState. If there are many kinds of changes, use useReducer.
  2. Do you need to do something outside React, such as load data or start a timer? Use useEffect.
  3. Do you need to remember something without updating the screen, or reach a real element? Use useRef.
  4. Do many components at different levels need the same data? Use useContext.
  5. Is the app slow because of a big calculation or many re-renders? Then try useMemo or useCallback.

Start with useState. Add the other hooks only when you have the problem they solve. Do not add useMemo and useCallback everywhere "just in case".

Common mistakes

MistakeWhat you seeFix
Calling a hook inside an if or loopError: Rendered more hooks than during the previous renderCall every hook at the top of the component
Calling a hook in a normal functionError: Invalid hook callCall hooks only in components or custom hooks
Using useRef for data the screen showsThe screen does not updateUse useState for values the screen shows
Forgetting the dependency array in useEffectThe effect runs after every renderAdd [ ] with the values to watch
Reading useContext without a ProviderYou always get the default valueWrap the components in <MyContext.Provider value={...}>
Adding useMemo to every small valueCode is harder to read, and not fasterUse it only for slow calculations

Check Yourself

Exercises

What to Remember

  • Hooks are functions starting with use. Call them only at the top of components or custom hooks.
  • State hooks remember data, effect hooks run code after rendering, refs remember without re-rendering, context shares data, and performance hooks skip work.
  • Start with useState. Reach for other hooks only when you have the problem they solve.

Next: Custom Hooks