ReactJS-使用localStorage作为useEffect的依赖项会导致无限循环



这段代码在console.log行给了我无限循环

const userInfo = JSON.parse(localStorage.getItem("user_info"));
const [filterSemester, setFilterSemester] = useState(SEMESTERS[0]);
const [scoreData, setScoreData] = useState(null);
useEffect(() => {
getData();
}, [userInfo, filterSemester]);
useEffect(() => {
console.log("scoreData: ", scoreData);
}, [scoreData]);
const getData = () => {
const params = {
student_id: userInfo?.student_info?.id,
school_year_id:
userInfo?.student_info?.class_info?.grade_info?.school_year_id,
semester: filterSemester.key,
};
getStudyInfoBySchoolYear(params).then((res) => {
if (res?.status === 200) {
setScoreData(res?.data?.data);
}
});
};

如果我从第一个useEffect的依赖数组中删除userInfo,循环就会消失,我想知道为什么?我根本没有在代码中更改它。

userInfo实际上正在发生变化。

它是一个功能性组件,因此组件中的所有代码都将在每次渲染中运行,因此,userInfo在每次渲染时都会被重新创建,因为它没有被声明为引用(使用useRef(,或者更常见的是,它没有被宣布为状态(使用useState(。

流程如下:

  1. 组件安装
  2. 第一个useEffect运行getData。第二个useEffect也运行
  3. getData将用setScoreData更新scoreData状态。后者将触发重新渲染,并且scoreData也已更改,因此将运行第二个useEffect
  4. 当渲染发生时,组件中的所有代码都将运行,包括userInfo声明(创建对它的新引用,除非localStorage.getItem("user_info")返回undefined(
  5. React检测到userInfo已更改,因此第一个useEffect将再次运行
  6. 该过程从步骤3开始重复

您可以更换

const userInfo = JSON.parse(localStorage.getItem("user_info"));

带有

const userInfo = React.useRef(JSON.parse(localStorage.getItem("user_info")));

和你的

useEffect(() => {
getData();
}, [userInfo, filterSemester]);

带有

useEffect(() => {
getData();
}, [userInfo.current, filterSemester]);

尝试这个

const userInfo = JSON.parse(localStorage.getItem("user_info"));
const [filterSemester, setFilterSemester] = useState(SEMESTERS[0]);
const [scoreData, setScoreData] = useState(null);
useEffect(() => {
getData();
}, [localStorage.getItem("user_info"), filterSemester]);
useEffect(() => {
console.log("scoreData: ", scoreData);
}, [scoreData]);
const getData = () => {
const params = {
student_id: userInfo?.student_info?.id,
school_year_id:
userInfo?.student_info?.class_info?.grade_info?.school_year_id,
semester: filterSemester.key,
};
getStudyInfoBySchoolYear(params).then((res) => {
if (res?.status === 200) {
setScoreData(res?.data?.data);
}
});
};

最新更新