I have react app and I'm using redux in order to manage state.
What suppose to happen:
Redux holds an object that contains an _id
string, and on a page I have a useEffect
that first checks that checks _id
is not an empty string and only after, invokes an async function onPlantTimelineMount()
to fetch data using the _id
.
When a user reloads the page, Redux state is default loaded where _id
is an empty string so the if statement inside the useEffect
is invoked, to fetch that item using a different async function ifUserRefreshPage()
, dispatch the item to Redux state, and only after invoke onPlantTimelineMount()
.
The Problem:
The ifUserRefreshPage()
successfully fetches the data and dispatch it to Redux state, but the onPlantTimelineMount()
still uses the state prior to the ifUserRefreshPage()
invocation - which means that _id
is still an empty string.
Worth mentioning:
Inside ifUserRefreshPage()
I serialize the fetched item (line 38), I dispatch it to Redux (line 39), console.log the fetched item (line 40 in the image), and I console.log the item in Redux state (line 41) and its still empty!!!!!!
HOW???
The Code:
const currentPlant = useAppSelector(state => state.plants.currentPlant)
const plantUpdates = useAppSelector(state => state.plants.currentPlant.updates)
const reduxPlants = useAppSelector(state => state.plants.plants)
const location = useLocation();
const { show: showSnackbar, component: snackBar } = useSnackbar();
async function ifUserRefreshPage() {
setIsFetching(true)
const plantId = location.pathname.split('/')[2];
try {
console.log(`ifUserRefreshPage invoked`);
const plantResponse = await fetchPlantById(plantId, '1')
const serializedPlant = plantManager.serializePlant(plantResponse.data) // line 38
dispatch(setCurrentPlant(serializedPlant)) // line 39
console.log(serializedPlant); // line 40
console.log(currentPlant); // line 41
const gardenResponse = await fetchMyGarden('1')
dispatch(addPlants(plantManager.serializeGarden(gardenResponse.data)))
} catch (err) {
console.log(`error while running ifUserRefreshPage function` + err);
showSnackbar("Failed to load Timeline", "error");
} finally {
setIsFetching(false)
}
}
async function onPlantTimelineMount() {
setIsFetching(true)
console.log(`ifUserRefreshPage invoked`);
try {
const response = await fetchPlantUpdates(currentPlant._id!)
if (response.success) {
dispatch(setUpdatesToCurrentPlant(plantUpdateManager.serializeUpdatesArray(response.data)))
}
} catch (err) {
showSnackbar("Failed to load Timeline", "error");
} finally {
setIsFetching(false)
}
}
useEffect(() => {
async function start() {
if (!currentPlant._id) {
await ifUserRefreshPage()
}
await onPlantTimelineMount()
}
start()
},[])