Morton
Morton

Reputation: 5760

react navigation deep linking not working when use Tabs Stack

Version:

"dependencies": {
  "react-native": "0.63.4",
  "@react-navigation/bottom-tabs": "^5.11.2",
  "@react-navigation/native": "^5.8.10",
  "@react-navigation/stack": "^5.12.8",
}

Test website link test://info_register?token=1111 successfully, I can see route.params includes token

but when I get into my Tabs screen, and try to to use test://setting_register?token=1111, App just open it doesn't navigate to SettingScreen and route.params is undefined

I take reference from official document https://reactnavigation.org/docs/5.x/configuring-links

What is wrong with my deep linking for Tabs ?

Here is my code:

index.js

import * as React from 'react';
import {NavigationContainer} from '@react-navigation/native';

import LoginStack from './LoginStack';

import Linking from './Linking';

const AppContainer = () => {
  return (
    <NavigationContainer linking={Linking}>
      <LoginStack />
    </NavigationContainer>
  );
};

export default AppContainer;

Linking.js

const config = {
  screens: {
    // set config for App init screen
    PersonalInfoScreen: {
      path: 'info_register/',
        parse: {
          token: (token) => `${token}`,
        },
    },
    // set config for Tabs screen
    Setting: {
      screens: {
        SettingScreen: 'setting_register/:token',
      },
    },
},
  },
};

const Linking = {
  prefixes: ['test://'],
  config,
};

export default Linking;

LoginStack.js

import * as React from 'react';
import {useSelector} from 'react-redux';
import {createStackNavigator} from '@react-navigation/stack';

import LoginScreen from '../screens/Login/LoginScreen';
import PersonalInfoScreen from '../screens/Login/PersonalInfoScreen';
import TabStack from './TabStack';

const Stack = createStackNavigator();

const LoginStack = () => {
  const {uid, userToken} = useSelector((state) => state.LoginRedux);

  const showLoginFlow = uid === '' || userToken === '' ? true : false;

  return (
    <Stack.Navigator
      initialRouteName={'LoginScreen'}
      screenOptions={{headerShown: false, gestureEnabled: false}}>
      {showLoginFlow ? (
        <>
          <Stack.Screen name="LoginScreen" component={LoginScreen} />
          <Stack.Screen
            name="PersonalInfoScreen"
            component={PersonalInfoScreen}
          />
        </>
      ) : (
        <>
          <Stack.Screen name="TabStack" component={TabStack} />
        </>
      )}}
    </Stack.Navigator>
  );
};

export default LoginStack;

TabStack.js

import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

const TabStack = () => {
  return (
    <Tab.Navigator
      screenOptions={...mySetting}
      tabBarOptions={...myStyle},
      }}>
      <Tab.Screen name={'Free'} component={FreeStack} />
      <Tab.Screen name={'Video'} component={VideoStack} />
      <Tab.Screen name={'News'} component={NewsStack} />
      <Tab.Screen name={'Consultation'} component={ConsulationStack} />
      <Tab.Screen name={'Setting'} component={SettingStack} />
    </Tab.Navigator>
  );
};

export default TabStack;

Upvotes: 2

Views: 7693

Answers (3)

Mansi
Mansi

Reputation: 11

I hope this would be helpful also

import React, { Component } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const MainStack = createStackNavigator();
const RootStack = createStackNavigator();
const Tab = createBottomTabNavigator();

const linking = {
  prefixes: ['myapp://'],
  config: {
    screens: {
      Main: {
        initialRouteName: "Tabbar",
        screens: {
          Tabbar: {
            screens: {
              Campaigns: {
                screens: {
                  Compaigns: {
                    path: 'Compaigns'
                  },
                  CampaignPreview: {
                    path: 'details/:camp_id'
                  }
                }
              }
            }
          }
        }
      }
    },
  },
};

export default class App extends Component {

  CompaignStack = () => {
    return (
      <Stack.Navigator>
         <Stack.Screen
          name="Compaigns"
          component={Compaigns}
        />
        <Stack.Screen
          name="CampaignPreview"
          component={CampaignPreview}
        />
      </Stack.Navigator>
    );
  };

  Tabbar = () => {
    return (
      <Tab.Navigator>
        <Tab.Screen
          name="Home"
          component={Home}
        />
        <Tab.Screen
          name="Campaigns"
          component={this.CompaignStack}
        />
      </Tab.Navigator>
    );
  };

  MainStackScreen() {
    return (
      <MainStack.Navigator
        initialRouteName='Login'
        screenOptions={{
          headerShown: false,
        }}>
        <MainStack.Screen
          name="Login"
          component={Login}
        />
        <MainStack.Screen
          name="Tabbar"
          component={this.Tabbar}
        />
      </MainStack.Navigator>
    );
  }

  render() {
    return (
      <NavigationContainer linking={linking}>
        <RootStack.Navigator mode="modal">
          <RootStack.Screen
            name="Main"
            component={this.MainStackScreen}
            options={{ headerShown: false }}
          />
        </RootStack.Navigator>
      </NavigationContainer>
    );
  }
}

Upvotes: 1

mohammad moussa
mohammad moussa

Reputation: 21

Just a note, it seems like whenever you are enabling debug-chrome configuration deep linking with react-navigation is not working, I disabled it and it worked!

Upvotes: 0

Fiston Emmanuel
Fiston Emmanuel

Reputation: 4849

If review nested navigation https://reactnavigation.org/docs/5.x/configuring-links/#handling-nested-navigators docs.

You have this navigation tree for SettingScreen:

TabStack -> Setting -> SettingStack -> SettingScreen.

Routes configuration should match this tree also as below:

const config = {
  screens: {
    // set config for App init screen
    PersonalInfoScreen: {
      path: "info_register/",
      parse: {
        token: (token) => `${token}`,
      },
    },
    // set config for Tabs screen 
    TabStack: {
      screens: {
        Setting: {
          screens: {
            SettingScreen: "setting_register/:token",
          },
        },
      },
    },
  },
};



Upvotes: 6

Related Questions