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>
);
我正在对 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>
);