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

时间:2018-12-23 20:11:41

标签: reactjs react-hooks

React Hooks documentation不要在循环,条件或嵌套函数内部调用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 个答案:

答案 0 :(得分:6)

The reference指出实际原因,

  

通过遵循此规则,可以确保每次渲染组件时都以相同的顺序调用Hook。这就是让React在多个useState和useEffect调用之间正确保留Hook的状态的原因。

并提供the example,说明为什么这样做很重要。

循环,条件和嵌套函数是常见的执行钩子的顺序可能会受到干扰的地方。如果开发人员确定循环等是合理的并且可以保证顺序,那么就没有问题。

实际上,如果将循环提取到函数中,则该循环将被视为有效custom hook

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>
  ));
}