Marc Pope
Marc Pope

Reputation: 375

React Navigation 5 Nested Screen can't get back to Primary Screen

I'm having trouble figuring out nested navigators. I have a bottomTabNavigator with these buttons:

Home
Stations
  -> StationDetail (StationScreen)
Shows
  -> ShowDetail (ShowScreen)

On my home tab, I have a horizontal scroll of the same stations as the stations page.

Problem: When I navigate from the home page to a station detail page using this code to navigate to a nested navigator, I can't navigate back to the main/root StationsScreen Tab

navigation.navigate('Stations', {
      screen: 'Station',
      station: props.station,
    });

However, If I navigate to the stations tab first, then go back to the home page, then click a station, it works as expected. How can I fix this behavior? I've seen things like "reset" but I am unsure where to put that. Here's a simplified excerpt of my code:

AppStack.js:

import React from 'react';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';

import HomeStack from './HomeStack';
import StationStack from './StationStack';
import ShowStack from './ShowStack';

const Tab = createBottomTabNavigator();

const AppStack = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeStack} />
      <Tab.Screen name="Stations" component={StationStack} />
      <Tab.Screen name="Shows" component={ShowStack} />
    </Tab.Navigator>
  );
};

export default AppStack;

HomeStack.js

import React from 'react';
import {View} from 'react-native';
import {createStackNavigator} from '@react-navigation/stack';
import TopBarRight from '../components/TopBarRight';
import HomeScreen from '../screens/HomeScreen';
import StationScreen from '../screens/StationScreen';
import {useNavigation} from '@react-navigation/native';

const Top = createStackNavigator();

const HomeStack = () => {
  const navigation = useNavigation();
  return (
    <Top.Navigator>
      <Top.Screen name="Welcome" component={HomeScreen} />
    </Top.Navigator>
  );
};

export default HomeStack;

HomeScreen.js (revelant parts)

<SafeAreaView styles={styles.container}>
  <StatusBar barStyle="light-content" />
  <ScrollView>
     <StationScroll />
  </ScrollView>
</SafeAreaView>

StationScroll just loads a list of station badges StationBadge.js

const StationBadge = (props: StationProps) => {
  const navigation = useNavigation();

  const onPress = () => {
    navigation.navigate('Stations', {
      screen: 'Station',
      station: props.station,
    });
    console.log(`station pressed: ${props.station.location}`);
  };

  return (
    <TouchableOpacity onPress={onPress}>
      <View style={styles.container}>
        <Image
          style={styles.image}
          source={{
            uri: `https://example.com/img/station-logos/${props.station.callsign}.png`,
          }}
        />
        <Text numberOfLines={1} style={styles.text}>
          {props.station.location}
        </Text>
      </View>
    </TouchableOpacity>
  );
};

export default StationBadge;

Here's also StationStack.js

import React from 'react';
import {View} from 'react-native';
import {createStackNavigator} from '@react-navigation/stack';
import StationsScreen from '../screens/StationsScreen';
import StationScreen from '../screens/StationScreen';
import {StackActions, useNavigation} from '@react-navigation/native';

const SS = createStackNavigator();

const StationStack = () => {
  const navigation = useNavigation();

  return (
    <SS.Navigator>
      <SS.Screen name="Stations" component={StationsScreen}/>
      <SS.Screen name="Station"  component={StationScreen} />
    </SS.Navigator>
  );
};

export default StationStack;

Upvotes: 3

Views: 2210

Answers (2)

Marc Pope
Marc Pope

Reputation: 375

I should have kept reading the documentation:

Rendering initial route defined in the navigator

By default, when you navigate a screen in the nested navigator, the specified screen is used as the initial screen and the initial route prop on the navigator is ignored. This behavior is different from the React Navigation 4.

If you need to render the initial route specified in the navigator, you can disable the behavior of using the specified screen as the initial screen by setting initial: false:

navigation.navigate('Stations', {
  screen: 'Station',
 initial: false,
});

Upvotes: 7

pacy.eth
pacy.eth

Reputation: 176

I hope you are doing well. As I understood this issue, you are trying to access a screen that is not in the same stack as the home screen. On the HomeStack, I suggest you add this line of code :

// HomeStack.js page 
...
...
import StationScreen from '../screens/StationScreen';
...
...
<Top.Navigator initialRouteName="Welcome">
  <Top.Screen name="Welcome" component={HomeScreen} />
  <Top.Screen name="Stations" component={StationsScreen} />
</Top.Navigator>

With this, you can switch from the home to the Stations and the inverse, please try this and tell if it worked.

Upvotes: 1

Related Questions