0

I use the following structure in my React Native project.

<NavigationContainer>
  <Stack.Navigator>
    <Stack.Screen name="Login" component={LoginScreen} />
    <Stack.Screen
      name="Home"
      component={HomeScreen}
      options={{
        headerRight: () => <SettingsButton />,
        presentation: 'modal',
      }}
    />
    <Stack.Screen
      name="Settings"
      component={SettingsScreen}
      options={{
        presentation: 'card',
      }}
    />
  </Stack.Navigator>
</NavigationContainer>

function SettingsButton() {
  const navigation = useNavigation();

  return (
    <Button 
      title="Settings" 
      onPress={() => navigation.navigate('Settings')} 
    />
  );
}

Whenever SettingsButton is pressed, I want to open my Settings window on the home screen (foreground window) and not the login screen (background/root window). Unfortunately, React Navigation uses the root window to push the screen and this happens (notice how the back button appears on the background window):

screenshot of the two windows

How can I make it so that it uses the foreground window?

Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
  • you are presenting as modal for home screen and card for setting screen. then it will appear like this only.. what is your exact requirment? actully your question is little bit confusing. – Manojkanth Jan 02 '22 at 18:00
  • @Manojkanth The issue is that the navigation push is happening not on the opened modal screen, but on the screen in the background. – Tamás Sengel Jan 02 '22 at 18:07
  • Since your home screen in the modal, Have you tried to dismiss your modal before pushing your card view(setting screen). – Manojkanth Jan 02 '22 at 18:18
  • @Manojkanth I don't want to do that, I want to push to the navigation stack on the modally displayed screen. – Tamás Sengel Jan 02 '22 at 18:19
  • 1
    i think you cant push a screen inside the modal.. if you want to open a modal over modal then its possible. If you want to open a setting screen inside the modal, then you have to use that setting screen as a component. – Manojkanth Jan 02 '22 at 18:22
  • @Manojkanth Are you sure about that? This seems like a pretty crucial thing that's missing. – Tamás Sengel Jan 02 '22 at 18:54
  • 1
    yeah... i faced a similar issue like this before. – Manojkanth Jan 03 '22 at 05:01
  • Your ux design seems kinda fked up to me here. Why would you try to open settings on the home screen? The Home Screen is for your content and shouldnt have anything to do with settings when you clearly seperate them. And why would you have a home screen as modal? Thats really confusing. Make your home screen default and the settings screen as modal to overlay the rest like you would do it in every normal flow – Maximilian Dietel Jan 11 '22 at 10:06

2 Answers2

1

Your Home screen is a modal and the settings screen is a card and you tried to open the card screen inside the modal screen, it's not possible, either you have to set settings as a modal, so it will pop on top of the Home or set the Home as a card, so it won't popup on top of the settings screen.

Srinath
  • 88
  • 7
1

Note: There is a separate issue here which may cause you trouble down the road. I've added a description below.

Regarding the question at hand, how about passing a stack to the modal?

export const Root = () => {
    const RootStack = useMemo(() => createStackNavigator(), []);
    const HomeStack = useMemo(() => createStackNavigator(), []);

    function renderHomeStack() {
        return (
            <HomeStack.Navigator>
                <HomeStack.Screen name="Home" component={HomeScreen} />
                <HomeStack.Screen name="Settings" component={SettingsScreen} />
            </HomeStack.Navigator>
        );
    }

    function renderRootStack() {
        return (
            <RootStack.Navigator>
                <RootStack.Screen name="Login" component={LoginScreen} />
                <RootStack.Screen
                    name="HomeStack"
                    options={{
                        presentation: 'modal',
                    }}
                    component={renderHomeStack}
                />
            </RootStack.Navigator>
        );
    }

    return renderRootStack();
};

You might note that react-navigation encourages the separation of the login stack and the main stack. You can read more about it here. If you don't, you might encounter multiple issues down the road such as:

  1. Blocking the back button in android to avoid going back to the login page after a successful login.
  2. Resetting navigation state to navigate more easily to inner pages with navigate:
    navigation.navigate('Root', { screen: 'Profile' });
    
  3. Implementing deep linking down the road to navigate based on a push notification.

The bottom line is that implementing navigation is considerably easier when the stacks are separated.

Guy
  • 12,488
  • 16
  • 79
  • 119