3

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;
Marc Pope
  • 335
  • 1
  • 14

2 Answers2

4

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,
});
Marc Pope
  • 335
  • 1
  • 14
1

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.

pacy.eth
  • 175
  • 2
  • 9
  • This way does work, I wasn't sure it was a good idea to have a screen linked in two different navigators (One in home, and one in stations list page that goes to this same page). Is this the standard way of doing this? Also, then it does not highlight the "stations" tab at the bottom tab navigator, it says in the "home" tab. – Marc Pope Dec 28 '20 at 20:10
  • I found the answer, initial: false – Marc Pope Dec 28 '20 at 21:39
  • It's good that you found the answer dear, it was a pleasure. If you are interested, let's connect on LinkedIn for sharing opportunities and experience https://www.linkedin.com/in/pacifique-linjanja – pacy.eth Dec 28 '20 at 22:38