REACT (https://www.kirupa.com/react/index.htm) BOOK (https://www.amazon.com/exec/obidos/ASIN/0134546318/kirupacom) Meet React Hooks by kirupa (https://www.kirupa.com/me/index.htm) | filed under Learning React (https://www.kirupa.com/react/index.htm) So far, the components we've built have been pretty well-behaved. They take in some props, they return some JSX, and that's about it. Nothing is remembered from one render to the next. Nothing happens outside of the component. If you gave the same props to one of these components a hundred times, you would get the same result a hundred times. Real apps need more than that. We need components that remember things, like what a user typed into a text box or whether a menu is open. We need components that do things after they show up on the screen, like starting a timer or asking a server for data. We need a way to hold on to an element in the DOM so that we can focus it or measure it. A plain function can't do any of this by itself, because it forgets everything the moment it finishes running. This is where hooks come in. In this tutorial, we are going to learn what hooks are, why they exist, the two rules you have to follow when using them, and take a quick tour of the hooks that React gives us. Don't worry about memorizing every one of them. The goal is to get comfortable with the idea so that the next few tutorials make a lot more sense. Onwards! What Is a Hook? A hook is a special function that lets your component plug into React's features. Every hook has a name that starts with the word use, such as useState, useEffect, or useRef. When you call one inside a component, you are asking React to do something on your behalf: remember a value, run some code after rendering, hand you a reference to an element, and so on. Here is a small component that uses three different hooks: import { useState, useEffect, useRef } from "react"; function Stopwatch() { const [seconds, setSeconds] = useState(0); const inputRef = useRef(null); useEffect(() => { const id = setInterval(() => { setSeconds((s) => s + 1); }, 1000); return () => clearInterval(id); }, []); return (
Seconds: {seconds}
{count}
; } Our useState call for name only happens sometimes, which is the problem. Why does that matter? React has no idea what the variable names in your code are. The way it figures out which piece of state belongs to which useState call is by the order in which the hooks are called. Think of it as React keeping a numbered list of slots for each component: the first hook call gets slot 1, the second gets slot 2, and so on. The following diagram shows what that looks like for the stopwatch we saw earlier: [Image: A component named Stopwatch with useState, useEffect, and useRef calls, each connected to a numbered slot that React keeps for it. The caption reads: same hooks, same order, every single render.] (https://www.kirupa.com/react/images/hooks_overview_144.png) If the order stays the same on every render, everything lines up. If a hook is sometimes skipped, the slots shift around, and React ends up handing the wrong value to the wrong hook. When that happens in development, React will stop with an error. If you run the broken component above and switch loggedIn from false to true, you'll get a warning about a change in the order of hooks, followed by the error Rendered more hooks than during the previous render. If you need to do something conditionally, put the condition inside the hook (or inside the code that uses what the hook gave you), rather than around it. Rule 2: Only Call Hooks from React Functions You can call hooks from two places: inside a function component, or inside your own custom hook (a function whose name starts with use, which we'll look at later). Don't call them from regular JavaScript functions, event handlers, or class components. You don't have to rely on memory for any of this. The linter that comes with the Vite React template has a rule that checks both of these for you, and your editor will underline the mistakes as you type. Note: There Is One Exception React has a newer function called use that is described as a hook but is allowed to be called inside if statements and loops. It is used for reading things like promises and context. It also can't be called inside a try/catch block. You won't need it for a while, but when you do, we'll look at it in the What's New in React 19 (https://www.kirupa.com/react/react_19_whats_new.htm) tutorial. A Tour of the Built-in Hooks React ships with a good number of hooks, and it can look like a lot at first. The good news is that they fall into a handful of groups, and a few of them cover the vast majority of what you'll do. Here is the lay of the land. State Hooks - useState: Remembers a value and re-renders your component when it changes. This is the hook you will use the most, and we'll start on it in the next tutorial. - useReducer: Also remembers a value, but you update it by sending in actions to a function you write. It is handy when your state has many moving parts. We'll look at it in Managing State with useReducer (https://www.kirupa.com/react/managing_state_with_usereducer.htm). Effect Hooks - useEffect: Runs code after your component has been drawn to the screen, such as starting a timer or fetching data. We'll spend a full tutorial on it in Effects with useEffect (https://www.kirupa.com/react/effects_with_useeffect.htm). - useLayoutEffect: Like useEffect, but it runs before the browser paints. You'll rarely need it, but it is useful for measuring elements. - useInsertionEffect: A very specialized one for people who write CSS-in-JS libraries. Most of us will never touch it. Ref Hooks - useRef: Holds on to a value that sticks around between renders without causing a re-render when it changes. It is most often used to get at a DOM element, which we'll see in Accessing DOM Elements in React (https://www.kirupa.com/react/accessing_dom_elements.htm). - useImperativeHandle: Lets a component decide which methods a parent can call through a ref. Another one you'll need only now and then. Context Hook - useContext: Lets a component read a value that was provided by something far above it in the component tree, without passing props through every level. We'll cover it in Sharing Data with Context (https://www.kirupa.com/react/sharing_data_with_context.htm). Performance Hooks - useMemo and useCallback: Remember the result of a calculation or a function so it doesn't have to be redone on every render. These used to show up everywhere, but newer tooling can often handle this for you. More on that in Avoiding Unnecessary Renders (https://www.kirupa.com/react/avoiding_unnecessary_renders.htm). - useTransition and useDeferredValue: Let you mark some updates as less urgent so that your app stays responsive while React works through them. Hooks for Forms, Data, and Everything Else - useActionState, useOptimistic, and useFormStatus: Introduced for working with forms and actions. We'll see them in the Forms in React (https://www.kirupa.com/react/forms_in_react.htm) tutorial and the React 19 tutorial. Note that useFormStatus is imported from react-dom rather than react. - use: Reads a promise or a context value, and (as we saw) is allowed to break the top-level rule. - useId: Generates a unique ID that is safe to use for things like connecting a label to an input. - useSyncExternalStore: Subscribes to a store that lives outside of React. This is mostly for library authors. - useDebugValue: Adds a label to your custom hooks in React DevTools. - useEffectEvent: A newer hook (React 19.2 and up) for reading the latest props or state from inside an effect without having to re-run the effect. That's the whole list. If you are just getting started, focus on useState, useEffect, useRef, and useContext. Those four will carry you a very long way, and the rest will make sense when you run into the problem each one was created to solve. The official hooks reference (https://react.dev/reference/react/hooks) is also a great place to look things up. Building Your Own Hooks One more thing before we move on. Because a hook is just a function that calls other hooks, you can create your own. If you find yourself writing the same combination of useState and useEffect in several components, you can move that combination into a function called something like useWindowWidth and reuse it everywhere. Those are called custom hooks, and they are one of the nicest things about working with React. They get their own tutorial, Creating Custom Hooks (https://www.kirupa.com/react/custom_hooks.htm), once we have more of the basics in place. Conclusion Hooks are how our function components remember things, react to the outside world, and hold on to DOM elements. They are regular functions whose names start with use, and they follow two rules: call them at the top level of your component, and call them only from components or other hooks. The reason for the first rule is that React tracks hooks by the order in which they are called, so that order has to be the same every time. We have seen the full list, but we only need to know a few of them well to get going. We'll start with the most important one by far, useState, in the very next tutorial. Next tutorial: Dealing with State (https://www.kirupa.com/react/dealing_with_state.htm)