Rules of Hooks – React (2024)

These docs are old and won’t be updated. Go to react.dev for the new React docs.

These new documentation pages teach modern React and include live examples:

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.

Hooks are JavaScript functions, but you need to follow two rules when using them. We provide a linter plugin to enforce these rules automatically:

Only Call Hooks at the Top Level

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls. (If you’re curious, we’ll explain this in depth below.)

Only Call Hooks from React Functions

Don’t call Hooks from regular JavaScript functions. Instead, you can:

  • ✅ Call Hooks from React function components.
  • ✅ Call Hooks from custom Hooks (we’ll learn about them on the next page).

By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.

ESLint Plugin

We released an ESLint plugin called eslint-plugin-react-hooks that enforces these two rules. You can add this plugin to your project if you’d like to try it:

This plugin is included by default in Create React App.

npm install eslint-plugin-react-hooks --save-dev
// Your ESLint configuration{ "plugins": [ // ... "react-hooks" ], "rules": { // ... "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies }}

You can skip to the next page explaining how to write your own Hooks now. On this page, we’ll continue by explaining the reasoning behind these rules.

Explanation

As we learned earlier, we can use multiple State or Effect Hooks in a single component:

function Form() { // 1. Use the name state variable const [name, setName] = useState('Mary'); // 2. Use an effect for persisting the form useEffect(function persistForm() { localStorage.setItem('formData', name); }); // 3. Use the surname state variable const [surname, setSurname] = useState('Poppins'); // 4. Use an effect for updating the title useEffect(function updateTitle() { document.title = name + ' ' + surname; }); // ...}

So how does React know which state corresponds to which useState call? The answer is that React relies on the order in which Hooks are called. Our example works because the order of the Hook calls is the same on every render:

// ------------// First render// ------------useState('Mary') // 1. Initialize the name state variable with 'Mary'useEffect(persistForm) // 2. Add an effect for persisting the formuseState('Poppins') // 3. Initialize the surname state variable with 'Poppins'useEffect(updateTitle) // 4. Add an effect for updating the title// -------------// Second render// -------------useState('Mary') // 1. Read the name state variable (argument is ignored)useEffect(persistForm) // 2. Replace the effect for persisting the formuseState('Poppins') // 3. Read the surname state variable (argument is ignored)useEffect(updateTitle) // 4. Replace the effect for updating the title// ...

As long as the order of the Hook calls is the same between renders, React can associate some local state with each of them. But what happens if we put a Hook call (for example, the persistForm effect) inside a condition?

 // 🔴 We're breaking the first rule by using a Hook in a condition if (name !== '') { useEffect(function persistForm() { localStorage.setItem('formData', name); }); }

The name !== '' condition is true on the first render, so we run this Hook. However, on the next render the user might clear the form, making the condition false. Now that we skip this Hook during rendering, the order of the Hook calls becomes different:

useState('Mary') // 1. Read the name state variable (argument is ignored)// useEffect(persistForm) // 🔴 This Hook was skipped!useState('Poppins') // 🔴 2 (but was 3). Fail to read the surname state variableuseEffect(updateTitle) // 🔴 3 (but was 4). Fail to replace the effect

React wouldn’t know what to return for the second useState Hook call. React expected that the second Hook call in this component corresponds to the persistForm effect, just like during the previous render, but it doesn’t anymore. From that point, every next Hook call after the one we skipped would also shift by one, leading to bugs.

This is why Hooks must be called on the top level of our components. If we want to run an effect conditionally, we can put that condition inside our Hook:

 useEffect(function persistForm() { // 👍 We're not breaking the first rule anymore if (name !== '') { localStorage.setItem('formData', name); } });

Note that you don’t need to worry about this problem if you use the provided lint rule. But now you also know why Hooks work this way, and which issues the rule is preventing.

Next Steps

Finally, we’re ready to learn about writing your own Hooks! Custom Hooks let you combine Hooks provided by React into your own abstractions, and reuse common stateful logic between different components.

Rules of Hooks – React (2024)
Top Articles
Brookfield Asset Management (BAM) Stock Forecast & Price Prediction 2025, 2030 | CoinCodex
About Our Organization — Undue Medical Debt
Foxy Roxxie Coomer
It’s Time to Answer Your Questions About Super Bowl LVII (Published 2023)
Minooka Channahon Patch
Federal Fusion 308 165 Grain Ballistics Chart
Ds Cuts Saugus
Gabrielle Abbate Obituary
Www Craigslist Louisville
27 Places With The Absolute Best Pizza In NYC
Carter Joseph Hopf
Bubbles Hair Salon Woodbridge Va
shopping.drugsourceinc.com/imperial | Imperial Health TX AZ
Audrey Boustani Age
What Is Njvpdi
Directions To O'reilly's Near Me
Nashville Predators Wiki
Simplify: r^4+r^3-7r^2-r+6=0 Tiger Algebra Solver
Invert Clipping Mask Illustrator
Milspec Mojo Bio
Lcwc 911 Live Incident List Live Status
Richland Ecampus
How to Watch the Fifty Shades Trilogy and Rom-Coms
Catherine Christiane Cruz
Uncovering The Mystery Behind Crazyjamjam Fanfix Leaked
SN100C, An Australia Trademark of Nihon Superior Co., Ltd.. Application Number: 2480607 :: Trademark Elite Trademarks
Roane County Arrests Today
Greyson Alexander Thorn
The Boogeyman (Film, 2023) - MovieMeter.nl
Pioneer Library Overdrive
Kroger Feed Login
Kitchen Exhaust Cleaning Companies Clearwater
'Conan Exiles' 3.0 Guide: How To Unlock Spells And Sorcery
Springfield.craigslist
Emily Katherine Correro
Ixlggusd
Southern Democrat vs. MAGA Republican: Why NC governor race is a defining contest for 2024
LEGO Star Wars: Rebuild the Galaxy Review - Latest Animated Special Brings Loads of Fun With An Emotional Twist
Today's Final Jeopardy Clue
Natashas Bedroom - Slave Commands
Property Skipper Bermuda
Restored Republic May 14 2023
Gym Assistant Manager Salary
Strange World Showtimes Near Century Stadium 25 And Xd
Unlock The Secrets Of "Skip The Game" Greensboro North Carolina
Ssc South Carolina
Samsung 9C8
The Pretty Kitty Tanglewood
Aznchikz
Grand Park Baseball Tournaments
Southwind Village, Southend Village, Southwood Village, Supervision Of Alcohol Sales In Church And Village Halls
Latest Posts
Article information

Author: Greg Kuvalis

Last Updated:

Views: 6213

Rating: 4.4 / 5 (55 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Greg Kuvalis

Birthday: 1996-12-20

Address: 53157 Trantow Inlet, Townemouth, FL 92564-0267

Phone: +68218650356656

Job: IT Representative

Hobby: Knitting, Amateur radio, Skiing, Running, Mountain biking, Slacklining, Electronics

Introduction: My name is Greg Kuvalis, I am a witty, spotless, beautiful, charming, delightful, thankful, beautiful person who loves writing and wants to share my knowledge and understanding with you.