reactjsreact-nativereact-navigationreact-navigation-v6react-error-boundary

React Native - How to handle error The action 'NAVIGATE' with payload .. was not handled by any navigator?


Im trying to handle the error

The action 'NAVIGATE' with payload .. was not handled by any navigator

  1. tried having a no route match. the documentation says:
const config = {
  screens: {
    Home: {
      initialRouteName: 'Feed',
      screens: {
        Profile: 'users/:id',
      },
    },
    NotFound: '*',
  },
};

Im not sure if I need to add anything else, but like that its not working.

  1. I tried using error boundary and wrap my navigator in this. my error boundary works fine but it doesnt catch navigation errs. Not sure if its not suppose to catch them or something is wrong with my code.

App.js


const App = () => {
    const config = {...}
        return (
        <NotificationsProvider>
            <Navigator linking={linking}/>
        </NotificationsProvider>
    );
}

Navigator.js


<NavigationContainer ref={navigationRef} linking={linking}>
   <MyStack />
</NavigationContainer>

MyStack:


const MyStack = () => {
    return (
      <ErrorBoundary
          FallbackComponent={FallbackWithoutReset}
          onError={onError}
          navigation={navigation}
      >
        <Stack.Navigator navigation={navigation}>
            <Stack.Group>
             ...
            </Stack.Group>
        <Stack.Group>
            </Stack.Screen>
            <Stack.Screen
                name="Settings"
                component={SettingsScreen} 
            />
        </Stack.Group>
    ...
        <Stack.Screen name="NotFound" component={NotFoundScreen} />
     </Stack.Navigator>
   </ErrorBoundary>
    )
}

Solution

  • You could use the onUnhandleAction function of the NavigationContainer component. As written in the documentation

    Function which is called when a navigation action is not handled by any of the navigators.

    By default, React Navigation will show a development-only error message when an action was not handled. You can override the default behavior by providing a custom function.

    Thus, you can catch any "was not handled by any navigator"-error via the onUnhandleAction function.

    Then, if you want to navigate to a fallback route, you could use the useNavigationContainerRef hook.

    Here is a minimal working example and the corresponding snack.

    import { Button, View } from 'react-native';
    import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
    import { createNativeStackNavigator } from '@react-navigation/native-stack';
    
    function HomeScreen({ navigation }) {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Button
            title="Not handled by any navigator"
            onPress={() => navigation.navigate('IDoNotExist')}
          />
        </View>
      );
    }
    
    const Stack = createNativeStackNavigator();
    
    function App() {
      const navigationRef = useNavigationContainerRef();
      return (
        <NavigationContainer ref={navigationRef} onUnhandledAction={(error) => {
          console.log("Using Fallback", error)
          navigationRef.navigate("Home")
        }}>
          <Stack.Navigator initialRouteName="Home">
            <Stack.Screen name="Home" component={HomeScreen} />
          </Stack.Navigator>
        </NavigationContainer>
      );
    }
    
    export default App;