Tuesday, May 14, 2024
 Popular · Latest · Hot · Upcoming
69
rated 0 times [  73] [ 4]  / answers: 1 / hits: 111785  / 6 Years ago, sun, november 25, 2018, 12:00:00

Given the following component, when I press down on the age selector and change the value to 15, such that I render a form without the driver license field, I get the error:



Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
at invariant (react-dom.development.js:55)
at finishHooks (react-dom.development.js:11581)
at updateFunctionComponent (react-dom.development.js:14262)
at beginWork (react-dom.development.js:15103)
at performUnitOfWork (react-dom.development.js:17817)
at workLoop (react-dom.development.js:17857)
at HTMLUnknownElement.callCallback (react-dom.development.js:149)
at Object.invokeGuardedCallbackDev (react-dom.development.js:199)
at invokeGuardedCallback (react-dom.development.js:256)
at replayUnitOfWork (react-dom.development.js:17113)
at renderRoot (react-dom.development.js:17957)
at performWorkOnRoot (react-dom.development.js:18808)
at performWork (react-dom.development.js:18716)
at flushInteractiveUpdates$1 (react-dom.development.js:18987)
at batchedUpdates (react-dom.development.js:2210)
at dispatchEvent (react-dom.development.js:4946)
at interactiveUpdates$1 (react-dom.development.js:18974)
at interactiveUpdates (react-dom.development.js:2217)
at dispatchInteractiveEvent (react-dom.development.js:4923)


Example code below:





const {useState} = React;

function App() {
const [name, setName] = useState('Mary');
const [age, setAge] = useState(16);

if (age < 16) {
return (
<div>
Name:{' '}
<input
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
<br />
Age:{' '}
<input
value={age}
type=number
onChange={e => {
setAge(+e.target.value);
}}
/>
</div>
);
}

const [license, setLicense] = useState('A123456');

return (
<div>
Name:{' '}
<input
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
<br />
Age:{' '}
<input
value={age}
type=number
onChange={e => {
setAge(+e.target.value);
}}
/>
<br />
Driver License:{' '}
<input
value={license}
onChange={e => {
setLicense(e.target.value);
}}
/>
</div>
);
}

ReactDOM.render(<App />, document.querySelector('#app'));

<script src=https://unpkg.com/[email protected]/umd/react.development.js></script>
<script src=https://unpkg.com/[email protected]/umd/react-dom.development.js></script>
<div id=app></div>




More From » reactjs

 Answers
19

The problem is that in the first render, 3 useState hooks were invoked - name, age and license but after the age is changed to a value below 16, the useState for license is no longer invoked, resulting in only the first 2 hooks being invoked. As the React docs state:




Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. 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.




The order of the hooks being called is important, and if we write code that causes hooks to not be called, React will not be able to match the hook call with its values.



The solution is to move the license hook up to the top of the function so that it gets called regardless whether it is needed or not.





const {useState} = React;

function App() {
const [name, setName] = useState('Mary');
const [age, setAge] = useState(16);
const [license, setLicense] = useState('A123456');

return (
<div>
Name:{' '}
<input
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
<br />
Age:{' '}
<input
value={age}
type=number
onChange={e => {
setAge(+e.target.value);
}}
/>
{age >= 16 && <span>
<br />
Driver License:{' '}
<input
value={license}
onChange={e => {
setLicense(e.target.value);
}}
/></span>
}
</div>
);
}

ReactDOM.render(<App />, document.querySelector('#app'));

<script src=https://unpkg.com/[email protected]/umd/react.development.js></script>
<script src=https://unpkg.com/[email protected]/umd/react-dom.development.js></script>
<div id=app></div>




[#53044] Wednesday, November 21, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
amari

Total Points: 736
Total Questions: 111
Total Answers: 90

Location: Saint Pierre and Miquelon
Member since Fri, Jan 28, 2022
2 Years ago
;