Deeplinking with modals

Current Behavior

When opening a deeplink URL that involves a modal the app has no stack to go back to, even though all of them have an initial route.

Profile settings is the only one that works but as you can see the name of the STACK and of the SCREEN are the same.
aside from that, inventory and message both navigate to the correct screen, but i can’t navigate back since there is no screen in the stack to handle it.

Expected Behavior

When the user uses any deep-link url it navigates to the correct screen, and if it’s a modal it has the appStack as the root of the stack.

How to reproduce

I’m running the following configuration for my linking:

const linkingConfig = {
  screens: {
    profileSettings: {
      initialRouteName:'appStack',
      screens: {
        profileSettings: 'settings'
      }
    },
    inventoryModalNav: {
      initialRouteName:'appStack',
      screens: {
        inventoryItem: 'create',
      }
    },
    messageModalNav: {
      initialRouteName:'appStack',
      screens: {
        messageDetail: 'messages/view/:messageId',
      }
    },
    appStack: {
      screens: {
        tasksStack: {
          path: 'tasks',
          screens: {
            taskDetails: 'view/:id'
          }
        },
        inventoryStack: 'inventory',
        messagesStack: 'messages'
      }
    }
  },
}

The followings are configured as modals:

  • messageModalNav
  • inventoryModalNav
  • profileSettings

Navigators

  • Root – StackNavigator
<RootStack.Navigator
    initialRouteName={routeName}
    screenOptions={Platform.OS === 'android' ? androidStackConfig : stackConfig}
    headerMode={"none"}
    mode="modal"
  >
    <RootStack.Screen name={RouteIdentifiers.loggedOutStack.name} component={LoggedOutStackNavigator} initialParams={initialParams}/>
    <RootStack.Screen name={RouteIdentifiers.onBoardingStack.name} component={OnBoardingStackNavigator} initialParams={initialParams}/>
    <RootStack.Screen name={RouteIdentifiers.appStack.name} component={Tabs} initialParams={initialParams}/>
    <RootStack.Screen name={RouteIdentifiers.inventoryModalNavigator.name} component={InventoryModalNavigator}/>
    <RootStack.Screen name={RouteIdentifiers.messageDetailModal.name} component={MessageModalNavigator}/>
    <RootStack.Screen name={RouteIdentifiers.sharedTaskStack.name} component={SharedTaskStackNavigator}/>
    <RootStack.Screen name={RouteIdentifiers.profileSettings.name} component={ProfileSettingsModalNavigator}/>
    <RootStack.Screen name={RouteIdentifiers.weather.name} component={WeatherNavigatorModal}/>
    <RootStack.Screen name={RouteIdentifiers.photoRequestModal.name} component={PhotoRequestModalNavigator}/>
  </RootStack.Navigator>
  • AppStack – StackNavigator
    <ApplicationTabs.Navigator
      tabBar={props => <BottomNavigationTab {...props} />}
      tabBarOptions={{keyboardHidesTabBar: true}}
      initialRouteName={RouteIdentifiers.mainDashboardStack.name}
    >
      <ApplicationTabs.Screen name={RouteIdentifiers.tasksStack.name} component={TaskStackNavigator} options={({ route }) => ({tabBarLabel: strings.tabActivities, tabBarVisible: showTabBar(route) })}/>
      <ApplicationTabs.Screen name={RouteIdentifiers.messagesStack.name} component={MessagesStackNavigator} options={({ route }) => ({tabBarLabel: strings.tabMessages, tabBarVisible: showTabBar(route) })}/>
      <ApplicationTabs.Screen name={RouteIdentifiers.mainDashboardStack.name} component={MainDashboardStackNavigator} options={({ route }) => ({tabBarLabel: strings.tabMainDashboard, tabBarVisible: showTabBar(route) })}/>
      <ApplicationTabs.Screen name={RouteIdentifiers.inventoryStack.name} component={InventoryStackNavigator} options={({ route }) => ({tabBarLabel: strings.tabInventory, tabBarVisible: showTabBar(route) })}/>
      <ApplicationTabs.Screen name={RouteIdentifiers.smartDevicesStack.name} component={SmartDevicesStackNavigator} options={({ route }) => ({tabBarLabel: strings.tabSmartDevices, tabBarVisible: showTabBar(route) })}/>
    </ApplicationTabs.Navigator>
  • Messages – StackNavigator
  <MessageDetails.Navigator
    
    headerMode={"none"}
    screenOptions={Platform.OS === 'android' ? androidStackConfig : stackConfig}

  >
  <MessageDetails.Screen name={RouteIdentifiers.messageDetail.name} component={MessageDetail}/>
  <MessageDetails.Screen name={RouteIdentifiers.survey.name} component={SurveyScreen}/>
  <MessageDetails.Screen name={RouteIdentifiers.safetyFirstDisclaimer.name} component={SafetyFirstDisclaimer}/>
  </MessageDetails.Navigator>
  • Profile – StackNavigator
  <ProfileSettingsNav.Navigator
    
    headerMode={"none"}
    screenOptions={Platform.OS === 'android' ? androidStackConfig : stackConfig}

  >
    <ProfileSettingsNav.Screen name={RouteIdentifiers.profileSettings.name} component = {ProfileSettings}/>
    <ProfileSettingsNav.Screen name={RouteIdentifiers.changePassword.name} component={ChangePassword}/>
    <ProfileSettingsNav.Screen name={RouteIdentifiers.confirmEmail.name} component={ConfirmEmail}/>
    <ProfileSettingsNav.Screen name={RouteIdentifiers.editHomeDetails.name} component={EditHomeDetails}/>
  </ProfileSettingsNav.Navigator>
  • Inventory – StackNavigator
  <InventoryNav.Navigator
    initialRouteName={RouteIdentifiers.inventoryDashboard.name}
    headerMode={"none"}
    screenOptions={Platform.OS === 'android' ? androidStackConfig : stackConfig}
   
  >
    <InventoryNav.Screen name={RouteIdentifiers.inventoryItem.name} component={InventoryItem} />
    <InventoryNav.Screen name={RouteIdentifiers.inventoryItemDetails.name} component={InventoryItemDetails}/>
    <InventoryNav.Screen name={RouteIdentifiers.tag.name} component={Tag}/>
    <InventoryNav.Screen name={RouteIdentifiers.tagInfo.name} component={TagInfo}/>
  </InventoryNav.Navigator>

Your Environment

software version
iOS 14.3
@react-navigation/native 5.9.2
react-native 0.63