Search code examples
react-nativereact-navigation-bottom-tab

React native : bottom navigation with dynamic initialRouteName implementation


I am a beginner in react native. I have gone through different related topics. But failed. This is my issues,

I have a bottom navigator with 4 items, say Dashboard, X, Patient and Y. Here is the optimised bottom navigator code.

   const Stack = createStackNavigator();
   const Bottom = createBottomTabNavigator();
    const Main = () => {
    return (
      <Bottom.Navigator
        initialRouteName="DashboardScreenStack"
        tabBarOptions={{
          style: {
            height: 70,
            paddingTop: 20,
            backgroundColor: '#F3F6FF',
          },
          activeTintColor: colors.navigationTextActive,
          inactiveTintColor: colors.navigationTextInactive,
          labelStyle: {
            fontSize: 15,
            marginTop: 15,
            paddingBottom: 10,
          },
        }}>
        <Bottom.Screen
          name="DashboardScreenStack"
          component={DashboardScreenStack}
          options={{
            tabBarLabel: 'Dashboard',
          }}
        />
        <Bottom.Screen
          name="X"
          component={X}
          options={{
            tabBarLabel: 'X',
          }}
        />
        <Bottom.Screen
          name="Patient"
          component={Patient}
          options={{
            tabBarLabel: 'Patient',
          }}
        />
        <Bottom.Screen
          name="Y"
          component={Y}
          options={{
            tabBarLabel: 'Y',
          }}
        />
      </Bottom.Navigator>
    );
  };

This is my code for Patient menu.

const Patient = (props) => {
  let resultData = null;
  var initialRoute = '';
  if (
    typeof props.route.params != 'undefined' &&
    props.route.params.result != null
  ) {
    
    resultData = props.route.params.result;
    initialRoute = 'PatientDashboardScreen';
  } else {
    initialRoute = 'AddPatientScreen';
  }
  
  return (
    <Stack.Navigator
      initialRouteName={initialRoute }>
      <Stack.Screen
        name="PatientDashboardScreen"
        component={PatientDashboardScreen}
        initialParams={resultData}
        options={{headerShown: false}}
      />
      <Stack.Screen
        name="TestScreen1"
        component={TestScreen1}
        options={{headerShown: false}}
      />
      <Stack.Screen
        name="TestScreen2"
        component={TestScreen2}
        options={{headerShown: false}}
      />
      <Stack.Screen
        name="AddPatientScreen"
        component={AddPatientScreen}
        options={{headerShown: false}}
      />
    </Stack.Navigator>
  );
};

There are 4 screens that should be shown in Patient menu. Out of those if I am selecting an item in my Dashboard menu I need to open "PatientDashboardScreen". And there will be some data available in props too. But on directly clicking 'Patient' menu, I need to move to "AddPatientScreen" where no data is passed.

I tried the above code. But only the initial click works. If I am selecting from list first, the always Patient menu is showing "PatientDashboardScreen" and if I am selecting Patient menu directly first, then always "AddPatientScreen" is shown on Patient menu selection.

Any help would be greateful. Thank you


Solution

  • Based on your question You have a bottom navigator and one of the screens has a nested stack navigator.

    The requirement here is to show a specific screen when pressing the bottom navigator button and redirect to a screen when opening from another screen in bottom navigator along with some parameters.

    This is one way to do this.

      <Tab.Screen
        name="Hospital"
        component={HospitalView}
        options={({ navigation }) => ({
          tabBarButton: (props) => (
            <TouchableOpacity
              {...props}
              onPress={() =>
                navigation.navigate('Hospital', { screen: 'Patient' })
              }
            />
          ),
        })}
      />
    

    You can have a custom onPress in your bottom navigator button which will use the navigate with the screen option which will take you to the specific screen.

    To navigate from another screen with parameters you can use the below option

       <Button
            title="Doctor"
            onPress={() =>
              navigation.navigate('Hospital', {
                screen: 'Doctor',
                params: { name: 'Doc 1' },
              })
            }
          />
    

    Your full code should look something similar to this

    const Stack = createStackNavigator();
    function Patient() {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>Patient Screen</Text>
        </View>
      );
    }
    
    function Doctor({route}) {
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>Doctor Screen</Text>
          <Text>{route?.params?.name}</Text>
        </View>
      );
    }
    
    function HomeScreen({ navigation }) {
      return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
          <Text>Home!</Text>
          <Button
            title="Doctor"
            onPress={() =>
              navigation.navigate('Hospital', {
                screen: 'Doctor',
                params: { name: 'Doc 1' },
              })
            }
          />
        </View>
      );
    }
    
    function HospitalView() {
      return (
        <Stack.Navigator>
          <Stack.Screen name="Doctor" component={Doctor} />
          <Stack.Screen name="Patient" component={Patient} />
        </Stack.Navigator>
      );
    }
    
    const Tab = createBottomTabNavigator();
    
    function MyTabs() {
      return (
        <Tab.Navigator>
          <Tab.Screen name="Home" component={HomeScreen} />
          <Tab.Screen
            name="Hospital"
            component={HospitalView}
            options={({ navigation }) => ({
              tabBarButton: (props) => (
                <TouchableOpacity
                  {...props}
                  onPress={() =>
                    navigation.navigate('Hospital', { screen: 'Patient' })
                  }
                />
              ),
            })}
          />
        </Tab.Navigator>
      );
    }
    

    You can refer this sample https://snack.expo.io/@guruparan/5f3f1d