If I use the following code:
App.js:
import useFoo from "./useFoo";
import "./styles.css";
export default function App() {
let foo = 3;
if (Math.random() > 0.5) {
foo = useFoo(6);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
{foo}
</div>
);
}
where useFoo()
is merely to return the square of a number:
useFoo.js
export default function useFoo(a) {
return a * a;
}
This can be shown on https://codesandbox.io/s/jolly-knuth-jwshws?file=/src/App.js
So:
-
if you keep on refreshing the resulting page, you do see a 3 and 36 at random, so it does seem like "a React Hook", in this case
useFoo()
doesn’t need to be at top level -
at work, I actually encountered a pattern which is
const [bar, useBar] = useBar(value1, value2);
and even thought it looks very similar to a useState()
, I found that useBar()
merely works like a function like useFoo()
above. That is, it doesn’t have the "keeping a state and bar
will stay the same" kind of magic like useState()
. (but on second thought, even useState() in fact gives a value back and assign it to the value
in const [value, setValue] = useState(value1)
, so there is real assignment going on, but just that useState()
chooses to return the same value if no useBar() is called).
But the question is:
- If I use the same thing:
let [bar, setBar];
if (true) {
[bar, setBar] = useBar(value1, value2);
}
then the Visual Studio Code with error and warning messages built in will complain it is a bug: that React Hooks must be at the top level. However, if I run the webapp, it still runs as normal. So the question is:
Do all React Hooks need to run at the top level? If they do, then why does useBar()
above work?
If only some React Hooks need to be at top level, then what determines that they must be at top level? Is it just by linting really? (so if you ignore the linting, the program will run into unexpected results? I suppose it will give a lint error instead lint warning, so that on the GitHub review, your coworker won’t approve it. But then, the useBar()
above can work despite the lint error, if it exists. So what determines whether it must be top level or not?
(that is, I found that sometimes the Hooks or Custom Hooks are merely like a function. And if it is function, it really doesn’t have the rule of needing to be at the top level).
2
Answers
React Hooks are functions that let you "hook into" React state and lifecycle features from function components. They allow you to use state and other React features without writing a class component. However, React Hooks must be called at the top level of a function component, before any early returns.
React relies on the order in which Hooks are called to maintain state and effects. Calling Hooks conditionally or inside loops can disrupt this order and lead to unexpected behavior. For example, if you call a Hook conditionally, React may not be able to track which Hooks have been called, and this can lead to errors.
In addition, calling Hooks inside loops can lead to performance problems. React will need to re-render the component every time the loop iterates, and this can be slow.
Therefore, it is best practice to always call React Hooks at the top level of a function component. This will help to ensure that your code is consistent and predictable.
Because having a predictable sequence is important.
Source
And
Source