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."
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.
Mine was finally resolved by just removing spaces in Stack.Screen's name.
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 yourHome
component:
navigation.navigate('Root');
It works, and the initial screen inside the
Root
component is shown, which isProfile
. 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 ofProfile
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With