反应useEffect警告以放置缺少的依赖项。但是依赖项值在挂钩中发生了变化

时间:2020-07-23 12:00:25

标签: reactjs react-hooks use-effect

我想在step的值更改时更改formStepTouched的值,所以我正在使用useEffect。但是useEffect发出警告,表明它缺少对formStepTouched的依赖。因为这是不断变化的值,将其放入依赖项数组将导致无限调用。

 const [step, setStep] = useState(0);
 const [formStepTouched, setFormStepTouched] = useState(
    Array(childrenArray.length)
      .fill(false)
      .map((_, idx) => idx === 0)
 )

 useEffect(() => {
    const newFormStepTouched = [...formStepTouched];
    newFormStepTouched[step] = true;
    setFormStepTouched(newFormStepTouched);
  }, [step]);

请参考下面的codeandbox链接: https://codesandbox.io/s/brave-gould-ymjt0?file=/src/App.js

如您所见,演示非常完美,但是显示了一条错误消息。如果添加了dependecy,useEffect将被无限调用。

如何清除错误消息。

2 个答案:

答案 0 :(得分:1)

   useEffect(() => {
    setFormStepTouched(prevState =>  {
      const newFormStepTouched = [...prevState]
      newFormStepTouched[step] = true
      return newFormStepTouched
    });
  }, [step]);

lint告诉您,外部依赖项可能会改变,您可以阅读更多here

答案 1 :(得分:1)

您可以将回调传递给状态设置器:

const { useEffect, useState } = React;

const App = () => {
  const [step, setStep] = useState(0);
  const [formStepTouched, setFormStepTouched] = useState(
    Array(5)
      .fill(false)
      .map((_, idx) => idx === 0)
  );

  useEffect(() => {
    //pass a callback to state setter
    setFormStepTouched((formStepTouched) => {
      if (formStepTouched[step] === true) {
        //nothing to change
        return formStepTouched;
      }
      return formStepTouched.map((s, i) =>
        i === step ? true : s
      );
    });
  }, [step]);

  return (
    <div>
      <button onClick={() => setStep(step + 1)}>
        nex step
      </button>
      <div>
        <pre>
          {JSON.stringify(formStepTouched, undefined, 2)}
        </pre>
      </div>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>