I'm trying to implement some listeners on react navigation using a functional component approach:
const ExampleComponent = () => {
const [subs, setSubs] = React.useState([]);
React.useEffect(() => {
setSubs([
navigation.addListener('willFocus', () => console.log('will focus')),
navigation.addListener('willBlur', () => console.log('will blur')),
navigation.addListener('didFocus', () => console.log('did focus')),
navigation.addListener('didBlur', () => console.log('did blur')),
]);
return () => {
setSubs([])
}
}, [])
return (
...
)
};
Following the advice: https://fantashit.com/navigation-listeners-firing-multiple-times-per-event/
However what seems to be happening is each listener is being called twice, and I'm unsure how to fix this?
It is fact for react native, whenever you add listeners for any mounted screen, the listeners are still active after screen is unmounted. And whenever such listeners try to change state of an unmounted screen, react native will generate warning.
so always try to add listeners whenever you mount screen and remove the same while unmounting
const ExampleComponent = () => {
const [subs, setSubs] = React.useState([]);
React.useEffect(() => {
setSubs([
navigation.addListener('willFocus', () => console.log('will focus')),
navigation.addListener('willBlur', () => console.log('will blur')),
navigation.addListener('didFocus', () => console.log('did focus')),
navigation.addListener('didBlur', () => console.log('did blur')),
]);
const unsubscribe = () =>{
navigation.removeAllListeners();
}
// Remove all listeners, because there have to be no listeners on unmounted screen
return () => unsubscribe();
}, [])
same can be achieved by the following in react navigation
useFocusEffect(
React.useCallback(() =>{
// Listening on the refresh event
RefreshEventEmitter.addListener("refresh", () => {
console.log("Refresh event emitted");
});
// ----------------------------------------------
// Removing all the listeners, so that screen does not re-render after unmounting..
const unsubscribe = () => {
RefreshEventEmitter.removeAllListeners();
};
// Returned function is called when screen is unmounted from display!!
return () => unsubscribe();
}, [])
);
useFocusEffect is called once when screen is mounted to the display and returned function by the same is called when screen is unmounted from the display.
As docs say:
addListener returns a function that can be called to unsubscribe from the event.
Try cleaning up each subscription in cleanup function:
React.useEffect(() => {
const unSubs = [
navigation.addListener('willFocus', () => console.log('will focus')),
navigation.addListener('willBlur', () => console.log('will blur')),
navigation.addListener('didFocus', () => console.log('did focus')),
navigation.addListener('didBlur', () => console.log('did blur')),
]
return function cleanup() {
unSubs.forEach((unSub) => {
unSub()
})
}
}, [])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With