Home > OS >  AppState listener continues to work even though I remove it
AppState listener continues to work even though I remove it

Time:10-18

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

CodePudding user response:

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.

  const isFocused = useIsFocused();
  const listener = useRef(null);

  useEffect(() => {
    listener.current = AppState.addEventListener('change', state => console.log(state));
  }, [])

  useEffect(() => {
    if (!isFocused && listener.current) {
      listener.current.remove();
    }
  }, [isFocused, listener]);

CodePudding user response:

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.

  • Related