Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native Navigation Error: The action navigate with payload {"name": 192.168.100.189:19000", "params":{}} was not handled by any navigator

I am using react-navigation with my React Native application.

I keep on getting an error that is supposedly a development-only warning and won't be shown in production.

How do I fix the error below?

console.error: "The action 'NAVIGATE' with payload
{"name":"192.168.100.189:19000","params":{}} was not handled by any
navigator.

Do you have a screen named '192.168.100.189:19000'?

If you'r trying to navigate to a screen in a nested navigator, see
https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nestd-navigator.

This is a development-only warning and won't be shown in production."
like image 647
preston Avatar asked Apr 13 '20 09:04

preston


3 Answers

There are two things potentially happening here:

IN MY CASE: I had different functions returning separate Stack Navigators as in the code below, I wanted the SettingsScreen to appear the very first time a user uses the app, so that they set the configurations, and next time they open the app again they would see the HomeScreen first (same flow with Authentication):

function SettingsStack() {
  return (
    <Stack.Navigator initialRouteName='Settings'>
      <Stack.Screen
        name="Settings"
        component={SettingsScreen}
        options={{
          title: 'SMS Recipient Number',
          headerShown: true,
          headerTitleAlign: 'center',
        }}
      />
      <Stack.Screen name="Home" component={HomeScreen} options={{ title: '', headerTransparent: true }}
      />
    </Stack.Navigator>
  );
}

function MainStack() {
  return (
    <Stack.Navigator initialRouteName='Home'>
      <Stack.Screen
        name="Update"
        component={UpdateScreen}
        options={{
          title: 'Update Recipient Phone',
          headerTitleAlign: 'center',
          headerShown: true
        }}
      />
      <Stack.Screen
        name="Security"
        component={PinScreen}
        options={{
          title: 'Provide PIN',
          headerTitleAlign: 'center',
          headerShown: true
        }}
      />
      <Stack.Screen
        name="Home"
        headerMode="screen"
        component={HomeScreen}
        options={({ navigation }) => ({
          headerTitle: '',
          headerTransparent: true,
          headerRight: () => (
            <Button
              icon={
                <Icon
                  name='settings'
                  type='feather'
                  color='grey'
                  onPress={() => navigation.navigate('Update')}
                  onLongPress={() => navigation.navigate('Update')}
                />
              }
              type="clear"
              buttonStyle={{ marginRight: 10 }}
            />
          ),
        })}
      />
    </Stack.Navigator>
  );
}

Settings Screen: Inside the settings screen after the user had provided ther required details, I used the following function to redirect to the HomeScreen:

transactEntry = async () => {
    const { phone_number } = this.state;

    if ((this.state.phone_number.trim() == "") || (this.state.phone_number.trim().length == 0)) {
        Alert.alert('Error:', 'Please enter valid phone number.');
        return
    }

    try {
        await AsyncStorage.setItem('@recipient_number', phone_number);
    } catch (error) {
        Alert.alert('Error:', 'Error setting recipient phone number!');
    }

    Keyboard.dismiss();

    let successToast = Toast.show('Recipient phone number set successfully.', {
        duration: Toast.durations.LONG,
        position: Toast.positions.TOP,
        shadow: true,
        animation: true,
        backgroundColor: 'black',
        hideOnPress: true,
        delay: 0,
        onShow: () => { },
        onShown: () => { },
        onHide: () => { },
        onHidden: () => { }
    });

    setTimeout(function () {
        Toast.hide(successToast);
    }, 3000);

    successToast;
    this.props.navigation.replace('Home');

};

NOTE: the part where i used this.props.navigation.replace('Home'); inside the SettingsScreen. This would work fine BUT the Home route that was being called was from that function SettingsStack() {...} function and not the function MainStack() {...} function.

So all the navigations from the Home Route at the top of the Stack would give me such an error because my active stack only had two routes, Settings Route and Home Route.

I later realised that I was forcing my app to look for Routes that were in a different Stack so i rewired the function MainStack() {...} and linked it with function SettingsStack() {...} function like below.

function SettingsStack() {
  return (
    <Stack.Navigator initialRouteName='Settings'>
      <Stack.Screen
        name="Settings"
        component={SettingsScreen}
        options={{
          title: 'SMS Recipient Number',
          headerShown: true,
          headerTitleAlign: 'center',
        }}
      />
      <Stack.Screen name="MainStack" component={MainStack} options={{ title: '', headerTransparent: true }}
      />
    </Stack.Navigator>
  );
}

function MainStack() {
  return (
    <Stack.Navigator initialRouteName='Home'>
      <Stack.Screen
        name="Update"
        component={UpdateScreen}
        options={{
          title: 'Update Recipient Phone',
          headerTitleAlign: 'center',
          headerShown: true
        }}
      />
      <Stack.Screen
        name="Security"
        component={PinScreen}
        options={{
          title: 'Provide PIN',
          headerTitleAlign: 'center',
          headerShown: true
        }}
      />
      <Stack.Screen
        name="Home"
        headerMode="screen"
        component={HomeScreen}
        options={({ navigation }) => ({
          headerTitle: '',
          headerTransparent: true,
          headerRight: () => (
            <Button
              icon={
                <Icon
                  name='settings'
                  type='feather'
                  color='grey'
                  onPress={() => navigation.navigate('Update')}
                  onLongPress={() => navigation.navigate('Update')}
                />
              }
              type="clear"
              buttonStyle={{ marginRight: 10 }}
            />
          ),
        })}
      />
    </Stack.Navigator>
  );
}

Take note of the <Stack.Screen name="MainStack" component={MainStack} options={{ title: '', headerTransparent: true }} /> line where the MainStack was now Connected to the SettingsStack.

IN BRIEF: Make sure that the Route that you have called resides in the same stack as the calling route OR just make sure that you have connected your Routes somehow eg putting the Stack function inside the Drawer Navigators function. At least there has to be a relationship or join.

like image 164
Tadiwanashe Avatar answered Sep 29 '22 01:09

Tadiwanashe


Mine was finally resolved by just removing spaces in Stack.Screen's name.

like image 10
muhammad mudassir Avatar answered Sep 29 '22 01:09

muhammad mudassir


As was the problem in my case, if you are trying to navigate to a screen in a nested navigator (as mentioned in the error), you indeed need to check the documentation at https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nestd-navigator (as, again, mentioned in the error):

Consider the following example:

function Root() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Profile" component={Profile} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator>
        <Drawer.Screen name="Home" component={Home} />
        <Drawer.Screen name="Root" component={Root} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

Here, you might want to navigate to the Root stack from your Home component:

navigation.navigate('Root');

It works, and the initial screen inside the Root component is shown, which is Profile. But sometimes you may want to control the screen that should be shown upon navigation. To achieve it, you can pass the name of the screen in params:

navigation.navigate('Root', { screen: 'Settings' });

Now, the Settings screen will be rendered instead of Profile upon navigation.

This may look very different from the way navigation used to work with nested screens previously. The difference is that in the previous versions, all configuration was static, so React Navigation could statically find the list of all the navigators and their screens by recursing into nested configurations. But with dynamic configuration, React Navigation doesn't know which screens are available and where until the navigator containing the screen renders. Normally, a screen doesn't render its contents until you navigate to it, so the configuration of navigators which haven't rendered is not yet available. This makes it necessary to specify the hierarchy you're navigating to. This is also why you should have as little nesting of navigators as possible to keep your code simpler.

like image 9
Ishita Sinha Avatar answered Sep 29 '22 01:09

Ishita Sinha