Reputation: 31
I've ran into an issue with react navigation event listener!
Logic: I want to fetch the cart details every time user comes to cart screen of my react-native app. To decide whether to fetch the cart details or not, I check for the cart id in the store. If cart id is null that means cart has not been created so just turn off the loader and do not fetch the cart details. On the other hand if there is a cart id in the store go fetch the cart details.
Scenario 1: Very first time, If I come to the cart screen when there is no cart id in the store it will not load the cart details: everything is good! But after subsequent visits to cart screen, it will not fetch the cart details even though there is a cart id in the store.
Scenario 2: Very first time, If I visit the cart screen when there exists a cart id in the store, it will fetch the cart details this time and on subsequent visits as well.
Possible Issue: So the issue seem to be that the event listener will use the cart value that will be provided on very first run and will not consider the updated value! Kindly point me in the right direction!
useEffect(()=>{
let cartId = context.store.cartReducer.cart.id;
const unsubscribe = props.navigation.addListener('focus', () => {
if(cartId) {
setIsDetailsLoading(true);
fetchCartDetails(context.dispatch, {cartId: cartId});
} else {
setIsDetailsLoading(false);
}
});
return unsubscribe;
}, []);
Solution
So eventually i figured it out that if you are using a value that may change, then you have to add it to the array(second parameter of useEffect hook) that was previously empty.
So the code looks like...
useEffect(()=>{
let cartId = context.store.cartReducer.cart.id;
const unsubscribe = props.navigation.addListener('focus', () => {
if(cartId) {
setIsDetailsLoading(true);
fetchCartDetails(context.dispatch, {cartId: cartId});
} else {
setIsDetailsLoading(false);
}
});
return unsubscribe;
}, [context.store.cartReducer.cart.id]);
Upvotes: 3
Views: 6824
Reputation: 2114
In React Navigation v5.x you should use "Navigation lifecycle"
Example from documentation:
import { useFocusEffect } from '@react-navigation/native';
function Profile() {
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
return () => {
// Do something when the screen is unfocused
// Useful for cleanup functions
};
}, [])
);
return <ProfileContent />;
}
Upvotes: 0
Reputation: 1568
For react navigation 4.x Try "willFocus" instead of "focus"
useEffect(()=>{
let cartId = context.store.cartReducer.cart.id;
const unsubscribe = props.navigation.addListener('willFocus', () => {
if(cartId) {
setIsDetailsLoading(true);
fetchCartDetails(context.dispatch, {cartId: cartId});
} else {
setIsDetailsLoading(false);
}
});
return unsubscribe;
}, []);
Upvotes: 1