ReactJS - 使用 localStorage 作为 useEffect 的依赖导致无限循环
ReactJS - use localStorage as a dependency for useEffect causes infinite loop
此代码在第 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
,循环就会消失,我想知道为什么?我根本没有在代码中更改它。
试试这个
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);
}
});
};
userInfo
实际上正在改变。
它是一个函数式组件,所以组件内的所有代码在每次渲染时都会 运行,因此,userInfo
在每次渲染时都会 re-created,因为它是未声明为引用(useRef
),或者更常见的是,声明为状态(useState
)。
流程如下:
- 组件挂载。
- 第
useEffect
运行s getData
。第二个useEffect
也是运行s.
getData
将用 setScoreData
更新 scoreData
状态。后者将触发 re-render,并且 scoreData
已更改,因此第二个 useEffect
将 运行.
- 渲染发生时,组件中的所有代码都将 运行,包括
userInfo
声明(创建对它的新引用,除非 localStorage.getItem("user_info")
返回 undefined
).
- React 检测到
userInfo
已更改,因此第一个 useEffect
将再次 运行。
- 该过程从 步骤 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]);
此代码在第 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
,循环就会消失,我想知道为什么?我根本没有在代码中更改它。
试试这个
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);
}
});
};
userInfo
实际上正在改变。
它是一个函数式组件,所以组件内的所有代码在每次渲染时都会 运行,因此,userInfo
在每次渲染时都会 re-created,因为它是未声明为引用(useRef
),或者更常见的是,声明为状态(useState
)。
流程如下:
- 组件挂载。
- 第
useEffect
运行sgetData
。第二个useEffect
也是运行s. getData
将用setScoreData
更新scoreData
状态。后者将触发 re-render,并且scoreData
已更改,因此第二个useEffect
将 运行.- 渲染发生时,组件中的所有代码都将 运行,包括
userInfo
声明(创建对它的新引用,除非localStorage.getItem("user_info")
返回undefined
). - React 检测到
userInfo
已更改,因此第一个useEffect
将再次 运行。 - 该过程从 步骤 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]);