【问题标题】:UseEffect infinite loop / runs forever even when state is not changedUseEffect 无限循环/即使状态没有改变也永远运行
【发布时间】:2021-11-06 23:38:42
【问题描述】:

我目前正在 useEffect 中放置一个 API GET 请求调用。这里的想法是在每次修改状态时“重新渲染”列表。

const[superheroes, setSuperheroes] = useState([]);

    useEffect(() => {
        apiCall('/superheroes', { method: 'GET'})
        .then(response => {
            response.json().then(response => {
                setSuperheroes(response);
            }).catch(x=> console.log("ERROR: " + x))
        })
    }, [superheroes])

即使superheroesstate 尚未更改,这样做也会导致无限循环调用。

我能清楚地解释为什么会这样吗?

编辑:澄清。我故意不使用空数组作为 useEffect() 的第二个参数,因为我不想运行一次。

【问题讨论】:

    标签: reactjs api react-hooks infinite-loop use-effect


    【解决方案1】:

    当您在 useEffect 中设置一个新数组(也是一个对象)时会发生这种情况

    function DoSomethingCrazy() {
      const [superheroes, setSuperheroes] = React.useState([]);
      React.useEffect(() => {
        console.log("i have arrived at the party!");
        setSuperheroes(["123123"]);
      }, [superheroes]);
    
      return <div>stuff goes here</div>;
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<DoSomethingCrazy />, rootElement);
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
        <div id="root"></div>

    尝试给useEffect放入一个空数组,让它只运行一次:

    useEffect(() => {
      apiCall("/superheroes", { method: "GET" }).then((response) => {
        response
          .json()
          .then((response) => {
            setSuperheroes(response);
          })
          .catch((x) => console.log("ERROR: " + x));
      });
    }, []);
    

    【讨论】:

    • 是的,我明白这一点。但我想要的是每次状态更改时都进行一次 API 调用,因此我没有放置空数组
    • 那么你需要有另一个状态。为了分离关注点。不建议让一个状态做很多事情。
    【解决方案2】:

    每次更换超级英雄时都会触发该效果。因为 useEffect 总是第一次执行,然后根据依赖的数组,代码在进行 ajax 调用的情况下得到响应,超级英雄被 setSuperheroes 更改,那么因为是 useEffect 的依赖,整个过程将再次发生。

    这里你不是重新渲染,你只是通过 ajax 重新获取。

    【讨论】:

      【解决方案3】:

      React 使用shallow compare 比较新状态和当前状态。

      当 API 调用成功时,setSuperheroes 将调用一个新的数组并且状态将有一个新的值。使用shallow compare,新状态总是与当前状态不同,因此组件总是重新渲染。

      【讨论】:

        猜你喜欢
        • 2022-08-18
        • 2019-10-28
        • 2019-04-14
        • 2019-07-22
        • 1970-01-01
        • 2020-03-13
        • 2020-01-11
        • 2018-06-09
        • 1970-01-01
        相关资源
        最近更新 更多