Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't React Hooks be called inside loops or nested function?

React Hooks documentation says to not call Hooks inside loops, conditions, or nested functions.

I understood that the order of execution was important so React can know which state corresponds to which useState call. Given that, it's obvious that a hook cannot be called inside a condition.

But I don't see what is the problem if we call useState inside a loop where the number of iterations doen't change over the time. Here is an example :

const App = () => {   const inputs = [];    for(let i = 0; i < 10; i++) {     inputs[i] = useState('name' + i);   }    return inputs.map(([value, setValue], index) => (     <div key={index}>        <input value={value} onChange={e => setValue(e.target.value)} />     </div>   )); }  export default App; 

Is there a problem with this code above ? And what is the problem of calling useState inside a nested function, if this function is called on every render ?

like image 895
Olivier Boissé Avatar asked Dec 23 '18 20:12

Olivier Boissé


People also ask

Why don't they call Hooks inside loops or nested functions?

Don't call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. React Hooks need to be called in the same order each time the component renders. Overreacted beautifully articulates several reasons why this is the case.

Why cant React Hooks be called conditionally?

This is not allowed because the number of hooks and the order of hook calls have to be the same on re-renders of our function components. To solve the error, we have to move the useState call to the top level and not conditionally call the hook.

How do you call React Hooks inside a function?

React Hooks must be called in a React function component or a custom React Hook function. error. In line 5, const [count, setCount] = useState(0); , we are calling the React useState Hook there. Even though the function is used as component in the App component, React will treat the component as a callback function.

Can React Hooks be used in functions?

Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don't work inside classes — they let you use React without classes. (We don't recommend rewriting your existing components overnight but you can start using Hooks in the new ones if you'd like.)


1 Answers

The reference states the actual cause,

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.

and provides the example that shows why this is important.

Loops, conditions and nested functions are common places where the order in which hooks are executed may be disturbed. If a developer is sure that a loop, etc. is justified and guarantees the order then there's no problem.

In fact, a loop would be considered valid custom hook if it was extracted to a function, a linter rule can be disabled where needed (a demo):

// eslint-disable-next-line react-hooks/rules-of-hooks const useInputs = n => [...Array(n)].map((_, i) => useState('name' + i)); 

The example above won't cause problems but a loop isn't necessarily justified; it can be a single array state:

const App = () => {   const [inputs, setInputs] = useState(Array(10).fill(''));   const setInput = (i, v) => {     setInputs(Object.assign([...inputs], { [i]: v }));   };    return inputs.map((v, i) => (     <div key={i}>        <input value={v} onChange={e => setInput(i, e.target.value)} />     </div>   )); } 
like image 52
Estus Flask Avatar answered Sep 19 '22 19:09

Estus Flask