skip to Main Content

I’m creating a React Native app that uses React Navigation.

Within 1 of my tabs, I have 3 screens. If I am in any of the screens that isn’t the home screen within that tab, and I tap on the tab icon, it takes me to the home screen of that tab. That’s great, fantastic.

However, it doesn’t trigger the useIsFocused hook and therefore doesn’t run a key function that needs to run when the screen is no longer displayed.

I would ideally like a way to find out if the tab has been pressed or the screen is unfocused from within my screen because I need to reference things on that screen.

I found this in the docs:

React.useEffect(() => {
  const unsubscribe = navigation.addListener('tabPress', (e) => {
    // Prevent default behavior
    e.preventDefault();

    // Do something manually
    // ...
  });

  return unsubscribe;
}, [navigation]);

But this doesn’t seem to work within the screen. Tapping the tab doesn’t trigger the useEffect.

This is my current code. Essentially, I am refetching some data for my screen every 10 seconds. When navigating away from my screen, I would like that interval to stop running. It works in every way apart from when tapping the tab icon in the tab navigation bar that this screen is a part of.

function setUpdateQueries() {
  let value = setInterval(refetchFunction, 10000, "active");
  setRefresh(value);
  console.log(value);
}
 
const isFocused = useIsFocused();
const navigation = useNavigation();
 
useEffect(() => {
  if (isFocused) {
    setUpdateQueries();
  }
  else {
    console.log("Clearing", refresh);
    clearInterval(refresh)
  }
},[isFocused])

2

Answers


  1. Chosen as BEST ANSWER

    So after leaving it and coming back to it, the answer is simple in their docs. Don't use useIsFocused(). Rather, use the useFocusEffect() hook like so:

    useFocusEffect(
        React.useCallback(() => {
          let value
          const firstRefresh = refetchFunction("active")
          value = setInterval(refetchFunction, 10000, "active");
          console.log(value);
          
          const unsubscribe = () => {
            console.log("Clearing", value);
            clearInterval(value)
          }
    
          return () => unsubscribe();
        }, [])
      );
    

    This picks up the tab press as well.


  2. Use the navigation.getState()

    The useNavigation hook gives you a state object. Which looks like this (attached below) for a tab navigator that is nested as an initial route inside a stack navigator.
    Notice that each navigation object has a state of its own. The main stack has an index and even the tab inside has an index which signifies which screen is currently focused.

    const state = {
      type: 'stack',
      key: 'stack-1',
      routeNames: ['Home', 'Profile', 'Settings'],
      routes: [
        {
          key: 'home-1',
          name: 'Home',
          state: {
            key: 'tab-1',
            routeNames: ['Feed', 'Library', 'Favorites'],
            routes: [
              { key: 'feed-1', name: 'Feed', params: { sortBy: 'latest' } },
              { key: 'library-1', name: 'Library' },
              { key: 'favorites-1', name: 'Favorites' },
            ],
            index: 0,
          },
        },
        { key: 'settings-1', name: 'Settings' },
      ],
      index: 1,
    };
    

    So in your case, you have a stack navigator nested inside the tab navigator. You can use the index property inside the nested state object of that specific navigator, to check whether the screen is still open or not. Something like this

    useEffect(() => {
        if(navigation.getState().state.index === yourScreenIndex){
          doSomething()
        };
      }, [navigation.getState()]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search