I added a listener to screen A as you can see below. But when I navigate to screen B, I see that this listener is still running. How can I solve this problem?
import React, { useEffect } from "react"
import { Button, AppState } from "react-native"
import { MainRoutes } from "../../navigation/routes"
const ScreenA = ({ navigation }) => {
useEffect(() => {
const appStateListener = AppState.addEventListener('change', state => console.log(state));
return () => appStateListener.remove();
}, [])
return (
<Button
title={"Next"}
onPress={() => {
navigation.reset({
index: 0,
routes: [{ name: MainRoutes.ScreenB }],
})
}} />
)
}
export default ScreenA
2
Answers
The
return
of the useEffect runs when the screen is unmounted.Navigating to a new screen will not unmount the old screen. Only an "orphaned" screen will be unmounted – i.e., on navigating back to screen A, screen B will be unmounted.
This scenario is described here in the docs: https://reactnavigation.org/docs/navigation-lifecycle/
To unmount when navigating away, an easy trick is to use the
useIsFocused
hook. You could save the listener in a ref.Even though you are navigating to Screen B, Screen A is not unmounted. Therefore, the code
appStateListener.remove();
will not get executed.One suggestion would be to add
appStateListener
to the global level (maybe in the App.js) since the app state will be used on many screens as the app grows and handling the listener in a centralized place will be helpful when the app grows too.Therefore, I don’t see any downside of adding it as a global listener.
Let’s discuss more on that if anybody has a better idea. Because I also wanna find the best practice.