-
Notifications
You must be signed in to change notification settings - Fork 16
On will/didFocus subscribe, stop firing the listener if current screen is focused #72
Description
Hi,
Today, when we add a will/didFocus listener on a screen, if that screen is currently focused, the listener will fire.
I think that behavior was implemented at a time where navigation.isFocused()
and withNavigationFocus
didn't exist yet, does not make sense anymore and is complicating the library usage.
For example, it makes it impossible to unsubscribe/resubscribe the same listener (or eventually closure/arrow function) without any side effect, which complicates the implementation of consuming code which need to ensure to register "stable listeners"
- https://github.com/react-navigation/react-navigation-core/pull/17/files#diff-ae2970cfcec67f1f42078a839a0a1f3f
- https://github.com/react-navigation/react-navigation-hooks/pull/8/files
- Fix for #6 in useNavigationEvent hooks#8 (comment)
- NavigationEvents creates an infinite loop if it changes the state react-navigation#5058
Also, one major usecase for navigation events is to refresh the screen data on focus.
The problem is that we use data loading systems that may already perform a fetch on mount (react-apollo, react-refetch...), so wiring onWillFocus={() => refetch()}
will actually trigger a duplicate fetch on mount.
As mentionned during the implementation of <NavigationEvents />
here, I solved this problem on my app with this kind of code:
handleWillFocus = (() => {
let count = 0;
return payload => {
if ( payload.action.type === NavigationActions.BACK ) {
return; // We don't want to refresh on back so that user does not loose pagination state
}
if ( count > 0 ) {
this.refreshTabData()
}
count++;
}
})();
Removing the willFocus
event after subscribe will solve that problem for all people that are trying to refetch on screen focus. If the behavior is intended it can still added back in componentDidMount anyway.
This is a breaking change and users should perform these migrations:
-
If user wants to fire something on mount if the screen is focused, he can implement that with
navigation.isFocused()
incomponentDidMount
-
If user wants to track focused state, he can use
withNavigationFocus
(also implemented later) or init his state withnavigation.isFocused()
If this is validated I'd be happy to send a PR to all the concerned projects of the system (core, NavigationEvents, hooks)