import React,{useState} from 'react';
function Car() {
const [st, setSt] = useState(0);
return <h2>a Car!</h2>;
}
export function App(props) {
const [count, setCount] = useState(0);
if(count===3) return ;
let b=<Car/>
return (
<div className='App'>
<Car/>
<button onClick={() => setCount(count + 1)}>
Click me {count}
</button>
</div>
);
}
when rendering app usestate at top level run fine. But when count reaches 3 when we press the button 3 times, it does early return rendering nothing. But there are hooks in car component that didnt run.So for hooks doesnt that count as early return that it did not render the hooks part in car.so all of the hooks didn’t run.Can you explain?
2
Answers
This code does not violate the rule about not having an early return before a hook, since the hook is in a separate component. The rule is just that you cannot have any hook calls that run conditionally within a component. Any conditions within the parent component, however, do not matter.
So if you formed your component like this:
Then you would be violating hook rules. But if
state2
was inside a second, conditionally rendered child component, as it is in your code above, the hook rules would not be being violated.When you write JSX like
<Car/>
or… you are not calling the Car function or executing any of the hooks it contains.
<Car />
is roughly the same as callingcreateElement(Car, null)
, and all that that does is produce a small object looking roughly like this:With more complicated JSX you make a larger object, but you’re again not calling the Car function or any hooks.
Once you’ve built up as large of an object as you like, you return it and thus you tell react "here are the things i would like to render to the page". If you’ve returned anything, react will recusively step through the child components and now it will end up calling
Car
and its hooks. But this happens after the return, and so react knows that you’ve ended one component and are starting another.The rules of hooks don’t say that you can’t change how many components you’re returning. You can return a
<Car/>
on one render, and then skip it on the next one. All that matters is that during the course ofApp
executing, you must call the same hooks in the same order.