简体   繁体   English

React useEffect 无限循环

[英]React useEffect infinite loop

I was experimenting with React a little and wanted to retrieve a json file I had on S3 bucket.我对 React 进行了一些试验,并想检索我在 S3 存储桶上的 json 文件。 I'm using the next code我正在使用下一个代码

import React, { useState, useEffect } from "react";
import { Storage } from "aws-amplify";

export default function Gallery(props){
  const [picList, setPicList] = useState([]);

  useEffect(() => {
    async function onLoad() {
      try{
        const picUrl = await Storage.get('list.json');
        const picr = await fetch(picUrl);
        const picjs = await picr.json();
        setPicList(picjs);
        console.log(picList);
      }
      catch(e){
        alert(e);
      }
    };
    onLoad();
  }, [picList]);



  function renderLander() {
    return (
      <div className="lander">
        <h1>Lander</h1>
      </div>
    );
  }

  return(
    <div className="Gallery">
      {renderLander()}
    </div>
  );
}

In the begining I was getting the error that when using setPicList , picList doesn't take the value of json file.一开始我收到错误,即在使用setPicListpicList不采用 json 文件的值。 I'm using console.log() to debug, so I'm sure that Storage.get is getting the right url, fetch() is getting the file json, but picList prints the default value [] .我正在使用console.log()进行调试,因此我确定Storage.get正在获取正确的 url, fetch()正在获取文件 json,但picList打印默认值[]

Now, with the code above instead I'm getting an infinite loop, but this time the value of picList is getting the right value (but it keeps fetching S3 for every render I think).现在,使用上面的代码,我得到了一个无限循环,但这次picList的值得到了正确的值(但它不断为我认为的每个渲染获取 S3)。

I was following this guide我正在遵循本指南

Edit: for completeness, picList is not getting updated if I remove the dependency, ie if I let [] instead of [picList] .编辑:为了完整picList如果我删除依赖项,即如果我让[]而不是[picList] ,则picList不会更新。

As Brian mentioned before, your useEffect is set to trigger whenever picList is changed.正如 Brian 之前提到的,您的 useEffect 设置为在 picList 更改时触发。 Since picList is being changed inside useEffect, this creates an infinite loop.由于 picList 在 useEffect 中被改变,这就造成了一个无限循环。

Since you're retrieving an object from S3, all you need to do is retrieve it once.由于您正在从 S3 检索对象,因此您需要做的就是检索它一次。

useEffect(() => {
    ...
}, []);

Ensures that the useEffect will only run once, when first rendered确保 useEffect 在第一次渲染时只运行一次

React hooks changes states asynchronously, so console.logging right after will produce either None or the previous value. React hooks 异步更改状态,因此之后的 console.logging 将生成 None 或先前的值。

What you need to do is add a conditional statement to your render function, to re-render the component when the state updates.您需要做的是在渲染函数中添加条件语句,以便在状态更新时重新渲染组件。

function renderLander() {
    return (
      <div className="lander">
        <h1>Lander</h1>
      </div>
    );
  }

  return(
    <div className="Gallery">
      {picList ? renderLander() : null}
    </div>
  );

You call setPicList in the callback function that listens for side effects off picList :你在回调函数中调用setPicList来监听picList副作用:

useEffect(() => {
    setPicList(someValue); //infinite loop because this causes a side effect
}, [picList]);

You are listening for changes to picList with useEffect and than make changes to picList when there is a change to picList in your useEffect call back function.您正在使用useEffect监听对picList的更改, picListuseEffect回调函数中对picList进行更改时对picList进行更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM