为什么不能在循环或嵌套函数内调用 React Hooks?

IT技术 javascript reactjs react-hooks
2021-04-09 06:49:17

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如果在每次渲染时都调用此函数,则在嵌套函数内部调用什么问题

1个回答

参考资料说明了实际原因,

通过遵循此规则,您可以确保每次渲染组件时都以相同的顺序调用 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>
  ));
}
没错。只要i < 10条件没有留下错误空间就可以。
2021-05-26 06:49:17
括号不匹配。它在其他方面也有效,stackblitz.com/edit/react-d1atmc
2021-05-28 06:49:17
至于Object.assign,数组完全没问题。它是不可变状态的单行代码,可以写成newInputs = [...inputs]; newInputs[i] = v; setInputs(newInputs). 我为不受控制的输入提供了修复。
2021-05-28 06:49:17
@UAvalos “不运行”是什么意思?答案包含可行的代码。如果您的情况不同,请考虑提出问题并提供可以复制您的问题的stackoverflow.com/help/mcve
2021-06-02 06:49:17
所以这句话不要在循环、条件或嵌套函数中调用 Hooks。是错的。如果遵守顺序,我们可以在循环内调用钩子
2021-06-11 06:49:17