Jorge Rivera
Jorge Rivera

Reputation: 775

How to properly wait for reset navigation in react native (react-navigator 6)?

React Navigation: Component in Tab Navigator not unmounting properly after parent Stack Navigator reset

The Problem I have a nested navigation structure with a Stack Navigator containing a Tab Navigator. When resetting the Stack Navigator to the initial route, components within the Tab Navigator are not unmounting properly, causing state-related issues.

// Navigation Structure
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();

function TabNavigator() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Profile" component={ProfileScreen} />
      {/* other tabs */}
    </Tab.Navigator>
  );
}

function RootNavigator() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Login" component={LoginScreen} />
      <Stack.Screen name="MainApp" component={TabNavigator} />
      {/* other screens */}
    </Stack.Navigator>
  );
}

When logging out from the Profile screen, I reset the navigation:

function ProfileScreen() {
  const navigation = useNavigation();
  
  const handleLogout = async () => {
    // Reset to Login screen
    navigation.reset({
      index: 0,
      routes: [{ name: 'Login' }]
    });
    
    // Clear app state
    clearAppState();
  };
  
  return (/* ... */);
}

The Issue Even though the navigation resets successfully, components within the Tab Navigator are not unmounting immediately. This causes issues because these components are still mounted when the app state is cleared, leading to errors as they try to access now-null values. I've verified this by adding unmount logs in the components:

useEffect(() => {
  console.log('Component mounted');
  return () => {
    console.log('Component unmounting');  // This log appears too late
  };
}, []);

Adding a delay before clearing the app state works, but feels hacky:

const handleLogout = async () => {
  navigation.reset({
    index: 0,
    routes: [{ name: 'Login' }]
  });
  
  await new Promise(resolve => setTimeout(resolve, 500));  // Why needed?
  clearAppState();
};

Questions

  1. Why aren't the Tab Navigator components unmounting immediately after the navigation reset?

  2. Is there a way to properly wait for all components to unmount before clearing app state?

  3. Is there a better pattern for handling logout in nested navigator scenarios?

Environment

I've tried:

  1. Using unmountOnBlur: true in the Tab Navigator options (this works but I rather not unmount the component on every blur event but only on logout)
  2. Using the navigation reference directly
  3. Adding navigation state change listeners
  4. Getting the root navigator via navigation.getParent()

None of these approaches ensure the components are unmounted before the app state is cleared.

Upvotes: 0

Views: 41

Answers (0)

Related Questions