charbel sarkis
charbel sarkis

Reputation: 21

React navigation title remains the same

I have nested navigators i.e a stack navigator within a stack navigator.

when naming the nested navigator the individual routes don't get their proper name but they get the name of the parent.

(i.e when I go move to main screen the title remains login/signup)

How do I solve this?

    export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        {/* <Stack.Screen name="HomeScreen" component={HomeScreen} />
        <Stack.Screen
          name="DisclaimerScreen"
          component={DisclaimerScreen}
          options={{headerLeft: null}}
        />
        <Stack.Screen name="Name Screen" component={NameScreen} />
        <Stack.Screen name="Date Screen" component={DateScreen} />
        <Stack.Screen name="GenderScreen" component={GenderScreen} />
        <Stack.Screen name="InfoScreen" component={InfoScreen} /> */}

        <Stack.Screen name="Login/Signup" component={Login} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}


function Login() {
  return (
    <LoginStack.Navigator headerTitle="Login">
      <LoginStack.Screen
        name="UsernameScreen"
        options={{title: 'Signup'}}
        component={UsernameScreen}
      />
      {/* TODO: ADD another screen for loggin in */}
      <LoginStack.Screen name="LoginScreen" component={LoginScreen} />
      <LoginStack.Screen
        name="MainScreen"
        options={{title: 'Home'}}
        component={Main}
      />
    </LoginStack.Navigator>
  );
}

Upvotes: 0

Views: 366

Answers (1)

bas
bas

Reputation: 15462

The reason it's not working is because you're trying to change a parent navigator's options inside a child navigator. First you don't need to set the title in options prop in the Login component for what you're trying to do:

function Login() {
  return (
    <LoginStack.Navigator>
      <LoginStack.Screen
        name="UsernameScreen"
        component={UsernameScreen}
      />
      {/* TODO: ADD another screen for loggin in */}
      <LoginStack.Screen name="LoginScreen" component={LoginScreen} />
      <LoginStack.Screen
        name="MainScreen"
        component={Main}
      />
    </LoginStack.Navigator>
  );
}

Then you can create a function to handle how the parent header title should change based on the child:

function getHeaderTitle(route) {
  // If the focused route is not found, we need to assume it's the initial screen
  // This can happen during if there hasn't been any navigation inside the screen
  
  const routeName = getFocusedRouteNameFromRoute(route) ?? 'UsernameScreen';

  switch (routeName) {
    case 'UsernameScreen':
      return 'Signup'
    case 'MainScreen':
      return 'Home';
    // etc...
  }
}

Then you can use the function in your parent stack navigator like this:

// ...
 <Stack.Navigator>
      <Stack.Screen 
         name="Login/Signup" 
         component={Login} 
         options={({ route }) => ({
            headerTitle: getHeaderTitle(route),
         })} 
      />
      // ...
</Stack.Navigator>
// ...

This approach is described very well in the documentation here: https://reactnavigation.org/docs/screen-options-resolution/#setting-parent-screen-options-based-on-child-navigators-state.

Be sure to import getFocusedRouteNameFromRoute from @react-navigation/native.

Upvotes: 1

Related Questions