React useEffect 无限循环

React useEffect infinite loop

我正在对 React 进行一些试验,想检索我在 S3 存储桶上的一个 json 文件。我正在使用下一个代码

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

一开始我得到的错误是当使用 setPicList 时,picList 没有采用 json 文件的值。我正在使用 console.log() 进行调试,所以我确定 Storage.get 正在获取正确的 url,fetch() 正在获取文件 json,但是 picList 打印默认值 [].

现在,使用上面的代码我得到了一个无限循环,但这次 picList 的值得到了正确的值(但我认为它会为每个渲染持续获取 S3)。

我关注了this guide

编辑:为了完整性,如果我删除依赖项,picList 不会更新,即如果我让 [] 而不是 [picList]

你在监听副作用的回调函数中调用setPicList关闭picList:

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

您正在使用 useEffect 监听对 picList 的更改,而不是在 useEffect 中对 picList 进行更改时对 picList 进行更改回调函数。

正如 Brian 之前提到的,您的 useEffect 设置为在 picList 更改时触发。由于 picList 在 useEffect 内部被更改,这会创建一个无限循环。

由于您是从 S3 检索对象,因此您只需检索一次即可。

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

确保 useEffect 在第一次渲染时只会 运行 一次

React 钩子异步更改状态,因此 console.logging 之后会产生 None 或先前的值。

您需要做的是在渲染函数中添加条件语句,以便在状态更新时重新渲染组件。

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

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