5

Start:

<NavigationContainer>
      <Stack.Navigator>
        {
          isLoading ? <Stack.Screen name="AuthLoadingScreen" component={AuthLoadingScreen} />
          : (
          user ? (
            <Stack.Screen  name="AuthenticatedStack" component={AuthenticatedStack} options={{headerShown: false}} />
            ) : (
              <Stack.Screen  name="NotAuthenticatedStack" component={NotAuthenticatedStack} options={{headerShown: false}} />
            )
          )
        }
      </Stack.Navigator>
    </NavigationContainer>

Authenticated stack:

const AuthenticatedStack = () => {
  return (
    <Drawer.Navigator initialRouteName="MainStack" drawerContent={props => <SideBar {...props} />}>
        <Stack.Screen name="MainStack" component={MainStack} options={({route}) => ({
            headerShown: shouldHeaderBeShown(route),title: getHeaderTitle(route),
          })} />
      </Drawer.Navigator>
  );
};

Main stack contain main screen with tab navigator and other navigators which I plan to navigate to from side menu buttons:

const MainStack = () => {
  return (
    <Stack.Navigator>
          <Stack.Screen name="main" component={MainTabNavigator} options={({route}) => ({
            headerShown: shouldHeaderBeShown(route),title: getHeaderTitle(route),
          })} />
          <Stack.Screen options={({route}) => ({
            title: getHeaderTitle(route),
          })} name="Welcome" component={WelcomeStack} />
        </Stack.Navigator>
  );
};

Main tab navigator is just few tabs:

const MainTabNavigator = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen
...

Home stack navigator:

const HomeStackNavigator = ({navigation, routes}) => {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} options={{
          headerLeft: () => (),
        }} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
};
Welcome stack:
const WelcomeStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen options={({route}) => ({
        headerShown: shouldHeaderBeShown(route),title: getHeaderTitle(route),
      })} name="welcome" component={WelcomeScreen} />
    </Stack.Navigator>
  );
};

I use this two function to show hide header to avoud double headers on tabs and to set titles:

function shouldHeaderBeShown(route) {
  const routeName = route.state ? route.state.routes[route.state.index].name : 'Home';

  switch (routeName) {
    case 'Home': return false;
  }
}

function getHeaderTitle(route) {
  const routeName = route.state ? route.state.routes[route.state.index].name : 'Home';

  switch (routeName) {
    case 'Home': return 'Home';
    case 'Settings': return 'Settings';
    case 'Welcome': return 'Welcome';
  }
}

And here I got to the problem:
This line: route.state ? route.state.routes[route.state.index].name if I switch between tabs I get all correctly state property is there and it's fine titles are set.
But If I from drawer navigate to Welcome then route doesn't have state property so it always pick 'Home' for title.
I pass this by making this line to:

const routeName = route.state ? route.state.routes[route.state.index].name : route.name;

Then it is showing Welcome title.
But I don't understand is this workaround ok or this screens can be set in a better way?

1110
  • 7,829
  • 55
  • 176
  • 334
  • I believe for a case like yours, a reproduction repository should be nominated to analyze. For example, I should see many things in your issue. If it is possible for you, make reproduction and push it on GitHub or GitLab or BitBocket then put its link here for having better answer. – AmerllicA Feb 19 '20 at 22:20
  • I got the same problem did you find a solution? – Marco Disco Nov 17 '20 at 15:44

2 Answers2

0

But If I from drawer navigate to Welcome

How do you navigate from drawer? If you're navigating by passing screen param, you can do this:

function getActiveRouteName(route) {
  // Access the tab navigator's state using `route.state`
  const routeName = route.state
    ? // Get the currently active route name in the tab navigator
      route.state.routes[route.state.index].name
    : // If state doesn't exist, we need to default to `screen` param if available, or the initial screen
      // In our case, it's "Home" as that's the first screen inside the navigator
      route.params?.screen || 'Home';

  return routeName;
}

Also seems the reason you even need this is because you have so many nested navigators. Maybe try to reduce nesting first? https://reactnavigation.org/docs/en/nesting-navigators.html#best-practices-when-nesting

satya164
  • 9,464
  • 2
  • 31
  • 42
0

I think you should use dispath not navigate. In navigate, you can't get updated state if you navigate to that screen again.


import {StackActions} from 'react-navigation';
pushAction = StackActions.push({
        routeName: 'FormsScreen',
        params: {
          id: result.id,
          flag: true,
          comments: result.note,
          type: result.type,
          date: result.created,
          accountName: result.accountName,
          accountId: result.accountId,
          accountType: result.accountType,
          bundleId: result.bundleId,
          formAnswer: JSON.parse(result.formAnswer),
        },
this.props.navigation.dispatch(pushAction);
Shing Ho Tan
  • 931
  • 11
  • 30