在useEffect中反应setState导致无限渲染周期

时间:2019-06-25 14:15:22

标签: javascript reactjs functional-programming

我正在尝试构建一个计算器,让您查看比较比率值。但是,按照我目前的方法,当用户编辑num1num2时,它将导致计算值的无限重新渲染。我想不出如何避免这种情况的发生,因为calc1和calc2都取决于比率,而且还取决于比率。

如何使用功能组件来实现这一目标?

import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import { useState } from "react";

function App() {
  let [num1, setNum1] = useState(5);
  let [num2, setNum2] = useState(10);
  let [ratio, setRatio] = useState();

  let [calc1, setCalc1] = useState();
  let [calc2, setCalc2] = useState();

  useEffect(() => {
    setRatio(num2 / num1);
  }, [num1, num2]);

  useEffect(() => {
    setCalc1(calc2 / ratio);
  }, [calc2, ratio]);

  useEffect(() => {
    setCalc2(calc1 * ratio);
  }, [calc1, ratio]);

  return (
    <div className="App">
      <input
        type="number"
        value={num1}
        onChange={e => setNum1(e.target.value)}
      />{" "}
      is to{" "}
      <input
        type="number"
        value={num2}
        onChange={e => setNum2(e.target.value)}
      />
      <p>Ratio is {ratio} therefore</p>
      <input
        type="number"
        value={calc1}
        onChange={e => setCalc1(e.target.value)}
      />{" "}
      ={" "}
      <input
        type="number"
        value={calc2}
        onChange={e => setCalc2(e.target.value)}
      />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit magical-herschel-nu5r9

1 个答案:

答案 0 :(得分:0)

这里有一个循环依赖性,当setCalc1触发然后calc1发生变化时,第二个useEffectsetCalc2触发将修改calc2是第一个useEffect的依赖项,将重新启动循环,依此类推。

useEffect(() => {
    setCalc1(calc2 / ratio);
  }, [calc2, ratio]);

  useEffect(() => {
    setCalc2(calc1 * ratio);
  }, [calc1, ratio]);

您必须重构代码以避免这种依赖性,例如使用包装calc1和calc2的对象

https://codesandbox.io/s/immutable-forest-typwu