Search code examples
expoexpo-router

Add an event listener to bottom tab with Expo router


I would like to add an event listener to one of my bottom tabs so I can trigger events when the user clicks on that tab. React navigation had a function navigator.addListener which allowed me to track this (see code below)

Does Expo router have some sort of equivalent?

import React, { useEffect } from 'react';
import { useNavigation } from '@react-navigation/native';

function MyTabScreen() {
  const navigation = useNavigation();

  useEffect(() => {
    const unsubscribe = navigation.addListener('tabPress', (e) => {
      console.log('Tab icon tapped');
      // Add your logic here
    });

    return unsubscribe;
  }, [navigation]);

  return (
    // Your tab screen content goes here
  );
}

export default MyTabScreen;

Solution

  • Ok, so I have found a solution to this.

    The Tabs component from expo router has got a property called screenListeners, and you just need to implement the tabPress listener.

    In my case, when the tabPress gets hit, I establish which tab was pressed, and if it is my tab of interest, I toggle a value in state. Then, in turn, I employ a useEffect in the tab's actual implementation to listen for that toggle, and execute the code I need to there.

    Inside my Tabs _layout.tsx

    import { Tabs } from 'expo-router/tabs'
    import useStore from 'src/store'
    
    export default function TabLayout() {
      const { stacksTabPress, toggleStacksTabPress } = useStore()
    
      return (
        <Tabs
          initialRouteName={'stacks'}
          screenOptions={}
          screenListeners={{
            // Monitor tab press and if 'test' tab is pressed, toggle value in zustand to trigger refetching of data from server
            tabPress: (e) => {
              const parts = e.target.split("-");
              const result = parts[0];
              if (result === 'test') {
                toggleStacksTabPress()
              }
            }
          }}
        >
          <Tabs.Screen
            name="test"
        />
    )}
    

    Inside my test index.tsx file

    const test = () => {
    
      const { stacksTabPress } = useStore()
    
      useEffect(() => {
        console.log("#### Execute my code from the tab press here ... ")
      }, [stacksTabPress])
      
      ...
    
    }