This code give me infinite loop at line 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);
}
});
};
If I remove userInfo
from the dependency array of the first useEffect
, the loop will gone, I wonder why? I didn't change it at all in the code.
CodePudding user response:
try this
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);
}
});
};
CodePudding user response:
userInfo
is actually changing.
It is a functional component, so all the code that is inside the component will run on every render, thus, userInfo
gets re-created on every render, because it was not declared as a reference (with useRef
) or, more commonly, as a state (with useState
).
The flow is as follows:
- The component mounts.
- The first
useEffect
runsgetData
. The seconduseEffect
also runs. getData
will updatescoreData
state withsetScoreData
. This latter will trigger a re-render, and alsoscoreData
has changed, so the seconduseEffect
will run.- When the render takes place, all the code within your component will run, including the
userInfo
declaration (creating a new reference to it, unlesslocalStorage.getItem("user_info")
is returningundefined
). - React detects
userInfo
as changed, so the firstuseEffect
will run again. - The process repeats from step 3.
You could replace your
const userInfo = JSON.parse(localStorage.getItem("user_info"));
with
const userInfo = React.useRef(JSON.parse(localStorage.getItem("user_info")));
and your
useEffect(() => {
getData();
}, [userInfo, filterSemester]);
with
useEffect(() => {
getData();
}, [userInfo.current, filterSemester]);