Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
718 views
in Technique[技术] by (71.8m points)

javascript - Why can't React Hooks be called inside loops or nested function?

React Hooks documentation says to not call Hooks inside loops, conditions, or nested functions.

I understood that the order of execution was important so React can know which state corresponds to which useState call. Given that, it's obvious that a hook cannot be called inside a condition.

But I don't see what is the problem if we call useState inside a loop where the number of iterations doen't change over the time. Here is an example :

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;

Is there a problem with this code above ? And what is the problem of calling useState inside a nested function, if this function is called on every render ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The reference states the actual cause,

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.

and provides the example that shows why this is important.

Loops, conditions and nested functions are common places where the order in which hooks are executed may be disturbed. If a developer is sure that a loop, etc. is justified and guarantees the order then there's no problem.

In fact, a loop would be considered valid custom hook if it was extracted to a function, a linter rule can be disabled where needed (a demo):

// eslint-disable-next-line react-hooks/rules-of-hooks
const useInputs = n => [...Array(n)].map((_, i) => useState('name' + i));

The example above won't cause problems but a loop isn't necessarily justified; it can be a single array state:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...