I am showing a list of users(profiles), and fetch it from some users DB. I am in the search page which include sub pages for diffrenet filters - like which users are currently online. Each time i am moving inside the search sub pages, i have to reset only once the main filtering variable in order ot get the correct result. The problem is the fetch request happpend before the setState variable changed. I saw other people asked how to fetch after, while i need it to first reset the variables of setState and the to go and fetch according to the correct values.
const [isPopUpShowState,setIsPopUpShowState] = useState(false);
const [profilesloading,setProfilesLoading] = useState(<Spinner/>);
const [profilesLength,setProfilesLength] = useState(0);
const [profilesPerPage] = useState(4);
const [searchStartPoint,setSearchStartPoint] = useState(0);
const [lastUserConnIndex,setLastUserConnIndex] = useState(1);
useEffect( ()=> {
restoreStatesToDefault(); // reset states+list --> the variables doesnt changed before the the fetch
getProfilesMatchingPage(); // init profiles
},[history.location.pathname]);
const restoreStatesToDefault = () => {
list = {};
setSearchStartPoint(0);
setLastUserConnIndex(1);
setProfilesLength(0);
}
const getSearchProfilesParmsInObj = () => {
const parmsObj = {};
if(currUser.loginObj){
parmsObj['isMale'] = !currUser.loginObj.data.isMale;
parmsObj['profilesPerPage'] = profilesPerPage;
parmsObj['searchStartPoint'] = searchStartPoint;
parmsObj['lastUserConnIndex'] = lastUserConnIndex;
parmsObj['allProfiles'] = list;
}
return parmsObj;
}
const getProfilesMatchingPage = () => {
switch(history.location.pathname){
case '/search/online':
dispatch(getProfilesOnline(getSearchProfilesParmsInObj(),setProfilesLoading,setLastUserConnIndex,setProfilesLength));
break;
case '/search/pics':
dispatch(getProfilesOnlyWithPics(getSearchProfilesParmsInObj(),setProfilesLoading,setLastUserConnIndex,setSearchStartPoint,setProfilesLength));
break;
case '/search/recently':
dispatch(getProfilesRecentlyVisited(getSearchProfilesParmsInObj(),setProfilesLoading,setLastUserConnIndex,setSearchStartPoint,setProfilesLength));
break;
case '/search/news':
dispatch(getProfilesNewUsersRegistered(getSearchProfilesParmsInObj(),setProfilesLoading,setLastUserConnIndex,setSearchStartPoint,setProfilesLength));
}
}
The problem is that both functions are called within the same lifecycle of the function, so the states haven't updated yet (They are within the same closure). After your useEffect finishes, then the next render is called with the updated state values, but they are not dependencies of your useEffect so they don't trigger it to fire again (which is a good thing in this case).
Basically what you want is two useEffect -> one is triggered on path change, and that one should update state that is a dependency of another useEffect that triggers the fetch.
A simple example would be:
const [shouldFetch, setShouldFetch] = useState(false) // Set this to true if you want to fetch on initial render
useEffect( ()=> {
restoreStatesToDefault(); // reset states+list --> the variables doesnt changed before the the fetch
setShouldFetch(true);
},[history.location.pathname]);
useEffect(() => {
if (shouldFetch) {
setShouldFetch(false);
getProfilesMatchingPage(); // init profiles
}
}, [shouldFetch])