React Hook is Called Conditionally
Error: React Hook is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a react hook after an early return? occurs when hooks are invoked conditionally or after a return of a value. When we deal with react hooks we have to take care of the following things.
- Don’t call Hooks inside loops, conditions, or nested functions.
- Don't use a return statement before invoking the hooks.
Let us discuss this in detail.
Don’t call Hooks inside loops, conditions, or nested functions
The hooks executed conditionally can lead to unexpected output and it is very hard to debug errors. So, the react hooks should be invoked in the same order between renderings.
Don’t call Hooks inside loops, conditions, or nested functions.
Don’t call hooks from regular JavaScript functions. Instead, call react hooks from custom hooks
Let's take an example of the below code which throws React error: react hook is called conditionally.
import { useState, useEffect } from 'react';
function App(){
const [count, setCount] = useState(0);
// Throws Error: React Hook "useEffect" is called conditionally
if(count > 10){
useEffect(()=>{
setCount(10);
});
}
return (<div> {count} </div>);
}
export default App;
In this example, we are invoking the useEffect
inside an if statement if(count > 10)
. This cause the error.
Solution:
To solve this issue, we can move the condition inside the useEffect as given below.
useEffect(()=>{
if(count > 10){
setCount(10);
}
});
Final code will look like:
import { useState, useEffect } from 'react';
function App(){
const [count, setCount] = useState(0);
useEffect(()=>{
if(count > 10){
setCount(10);
}
});
return (<div> {count} </div>);
}
export default App;
Don't use a return statement before invoking the hooks
Always use hooks at the top level of your react function, before any early returns.
Here is an example of how the error occurs.
import React, { useEffect, useState } from "react"
function App(){
const [isLoading, setIsLoading] = useState(true)
// Throws Error: React Hook "useEffect" is called conditionally
if (isLoading) {
return <label>Loading..</label>
}
useEffect(() => {
// Do something
setIsLoading(false)
}, [])
return (<div>App</div>);
}
export default App
React is throwing the above error because we are calling useEffect after the return statement( return <label>Loading..</label>
). Make sure all hooks are defined before any return statement.
Solution
To solve the error, we can reorder the return statement and call react hooks at the top level as given below.
import React, { useEffect, useState } from "react"
const App = () => {
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
// Do something
setIsLoading(false)
}, []);
if (isLoading) {
return <label>Loading..</label>
}
return (<div>App</div>);
}
export default App
Use ESLint Plugin to enforce react hook rules
Use the ESLint plugin called eslint-plugin-react-hooks
that enforces rules for hooks. we can install this plugin to our project using the below command.
npm install eslint-plugin-react-hooks --save-dev
ESLint configuration is given below.
// 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
}
}
For more deep knowledge, read react doc.
On datainfinities.com, Read articles all around JavaScript, React, Node.js, PHP, Laravel, and Shopify.
Related Blogs
The style prop expects a mapping from style properties to values, not a string
Too many re-renders. React limits the number of renders to prevent an infinite loop
How to pass event and parameter onClick in React
Get the Mouse Position (coordinates) in React
Build password strength checker in React
Create a Back button with React Router
How to get window width and height in React
How to create a scroll to top button in React
Explore All Blogs