Reputation: 4705
The first rule of Hooks is to only call hooks at the top level, i.e. "Don’t call Hooks inside loops, conditions, or nested functions". The docs explains pretty clearly with an example for calling Hooks inside conditions, but not for the other two cases: loops and nested functions.
Are there examples where something can go wrong when calling Hooks inside loops and nested functions? Moreover, isn't a custom hook just a nested function?
The provided answers for these two related questions here and here unfortunately only give the correct examples.
Upvotes: 5
Views: 2724
Reputation: 22324
Example of variable-length loop:
const {useState} = React
const WrongLoop = () => {
const [count, setCount] = useState(1)
for (let i = 0; i < count; i++) {
const [x, setX] = useState(i)
}
const [unknownOrder, setUnknownOrder] = useState('some state')
return <button onClick={() => setCount(c => c+ 1)}>{count} {unknownOrder}</button>
}
ReactDOM.render(<WrongLoop />, document.getElementById('root'))
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Example of nested function that would be hard to detect by eslint (custom hooks are a special case - when using the use...
prefix in function name, it's usage in the component can be statically analyzed by eslint):
const {useState} = React
const fn = () => {
const [x, setX] = useState() // is it OK to use hooks unconditionally here?
}
const WrongFn = () => {
const [count, setCount] = useState(1)
if (count === 1) {
fn() // OK to use normal functions conditionally.. but what if there's a hook inside?
}
const [unknownOrder, setUnknownOrder] = useState('some state')
return <button onClick={() => setCount(c => c+ 1)}>{count} {unknownOrder}</button>
}
ReactDOM.render(<WrongFn />, document.getElementById('root'))
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Upvotes: 5