Why can't react hooks be used inside condition or loop?
Mar 15, 2023
In order to find the answer to the question in the title, let's write a simple implementation of the hook. For that, let's consider the useState hook,
const React = () => {
let state = [];
let index = 0;
const useState = (initialValue) => {
const localIndex = index;
index++;
if (state[localIndex] === undefined) {
//works only when component mounts
state[localIndex] = initialValue;
}
const setter = (newValue) => {
state[localIndex] = newValue;
// trigger a re-render
};
return [state[localIndex], setter];
};
return { useState };
};the above is a simple implementation of the useState hook. In the actual case, it will look different.
Few points to note:
- Here we use the array data structure for implementing hooks.
- The states are stored in the consecutive indices of the array called state - (will explain this later section)
Use the hook in a component:
const { useState } = React();
const Component = () => {
const [user1, setUser1] = useState("john");
const [user2, setUser2] = useState("jane");
};
Component() // simulate mounting of the componentin this component the state will look like this: ['john', 'jane']
You have already understood that the values are stored in the consecutive cells of the array state.
The state user1 will take index 0, user2 will take index 1, and so on.
You might already get the answer to the question, but let's go further.
Let's try to update the first state user1 and also update the component a bit
const { useState } = React();
const Component = () => {
const [user1, setUser1] = useState("john");
if (user1 !== "john doe") {
const [user2, setUser2] = useState("jane");
}
const [user3, setUser3] = useState("richard");
if (user1 === "john") {
setUser1("john doe"); // this will trigger a re-render
}
};
Component() // Mounting
Component() // Simulate re-rendering after updating the state user1Now the hook is used inside an if condition.
During the first rendering, user1 will have the value john, user2 will have the value jane, and user3 will have the value richard. This means that all the hooks will work and the state inside React will look like this: ['john', 'jane', 'richard'].
But we are updating the state user1 at the end of the component, so again, the state inside React will be ['john doe', 'jane', 'richard']. And since we update the state, React will trigger a re-render.
Now we are at the most important point.
During the re-render, the state user1 has the value john doe, which means that the if condition is false and the second hook does not work, but the third hook works just normally. This results in user1 looking at index 0, user2 getting skipped, and user3 looking at index 1 of the state array of React. Thus during re-render, user3 will have the value jane (not richard).
Conclusion
In conclusion, hooks cannot be used inside conditions or loops because it can lead to unpredictable outcomes and inconsistencies in the state values. When a hook is called inside a condition or loop, it might not always run on every render, which can result in unexpected behavior. Therefore, it is important to use hooks at the top level of the component to ensure that they run consistently on every render and make it more readable.
However, there may be some cases where hooks need to be called inside conditions or loops, in which case it is important to carefully consider the impact on the state values and ensure that the hook runs consistently.
References:
https://medium.com/the-guild/under-the-hood-of-reacts-hooks-system-eb59638c9dba
https://www.youtube.com/@PhilipFabianek