React Hooks 文档说不要在循环、条件或嵌套函数中调用 Hooks。
我知道执行顺序很重要,所以 React 可以知道哪个状态对应于哪个 useState 调用。鉴于此,很明显,钩子不能在条件中调用。
但是,如果我们在一个循环中调用useState
,其中迭代次数不会随时间变化,我看不出有什么问题。这是一个例子:
const App = () => {
const inputs = [];
for(let i = 0; i < 10; i++) {
inputs[i] = useState('name' + i);
}
return inputs.map(([value, setValue], index) => (
<div key={index}>
<input value={value} onChange={e => setValue(e.target.value)} />
</div>
));
}
export default App;
上面的代码有问题吗?如果在每次渲染时调用该函数,那么在嵌套函数中调用useState
有什么问题?
参考说明实际原因,
通过遵循此规则,您可以确保每次渲染组件时都以相同的顺序调用 Hook。这就是允许 React 在多个 useState 和 useEffect 调用之间正确保留 Hooks 状态的原因。
并提供了说明为什么这很重要的示例。
循环、条件和嵌套函数是钩子执行顺序可能受到干扰的常见位置。如果开发人员确定循环等是合理的并保证顺序,那么就没有问题。
事实上,如果循环被提取到函数中,它将被视为有效的自定义钩子,可以在需要时禁用 linter 规则(演示):
// eslint-disable-next-line react-hooks/rules-of-hooks
const useInputs = n => [...Array(n)].map((_, i) => useState('name' + i));
上面的例子不会引起问题,但循环不一定是合理的;它可以是单个数组状态:
const App = () => {
const [inputs, setInputs] = useState(Array(10).fill(''));
const setInput = (i, v) => {
setInputs(Object.assign([...inputs], { [i]: v }));
};
return inputs.map((v, i) => (
<div key={i}>
<input value={v} onChange={e => setInput(i, e.target.value)} />
</div>
));
}