的问题是,在第一渲染,3个useState钩被调用-name,age和license但年龄变更后的值低于16时,useState为license不再被调用,导致只有第一2个钩子被调用。正如Reactdocs所述:
不要在循环,条件或嵌套函数中调用Hook。相反,请始终在您的React函数的顶层使用挂钩。通过遵循此规则,可以确保每次渲染组件时都以相同的顺序调用Hook。那是什么让反应正确保存多个鱼钩之间的状态useState和useEffect来电。
钩子的调用顺序很重要,如果我们编写导致钩子不被调用的代码,React将无法将钩子调用与其值匹配。
解决方案是将license钩子移到函数顶部,以便无论是否需要它都可以调用。
const {useState} = React;function App() { const [name, setName] = useState(’Mary’); const [age, setAge] = useState(16); const [license, setLicense] = useState(’A123456’); return ( <div> Name:{’ ’} <inputvalue={name}onChange={e => { setName(e.target.value);}} /> <br /> Age:{’ ’} <inputvalue={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/react@16.7.0-alpha.0/umd/react.development.js'></script><script src='https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js'></script><div id='app'></div>解决方法
给定以下组件,当我按下年龄选择器并将其值更改为15时,我呈现了没有驾驶执照字段的表单,则会收到错误消息:
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)
下面的示例代码:
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:{’ ’} <inputvalue={name}onChange={e => { setName(e.target.value);}} /> <br /> Age:{’ ’} <inputvalue={age}type='number'onChange={e => { setAge(+e.target.value);}} /> <br /> Driver License:{’ ’} <inputvalue={license}onChange={e => { setLicense(e.target.value);}} /> </div> );}ReactDOM.render(<App />,document.querySelector(’#app’));<script src='https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js'></script><script src='https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js'></script><div id='app'></div>