3

I am trying deeplinking in React-Native. The code works properly when the app is in the background. But once I remove the app from background and try to launch it using the link in safari. The app is launched with details screen. But I could not find previous (Home) screens in the Navigation Stack. Please find the code below:

/* eslint-disable react-native/no-inline-styles */
import 'react-native-gesture-handler';
import React from 'react';
import {TouchableOpacity, Text, View} from 'react-native';
import {useLinking, NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';

const HomeScreen = ({navigation}) => {
  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
      }}>
      <Text>Home Screen</Text>
      <TouchableOpacity
        onPress={() => {
          navigation.navigate('Details', {itemId: 40});
        }}>
        <Text>Go to Details</Text>
      </TouchableOpacity>
    </View>
  );
};

const DetailScreen = ({route, navigation}) => {
  return (
    <View
      style={{
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
      }}>
      <Text>Details Screen</Text>
      <Text>Item Id: {route.params.itemId}</Text>
      <TouchableOpacity onPress={() => navigation.goBack()}>
        <Text>Go Back</Text>
      </TouchableOpacity>
    </View>
  );
};

const Stack = createStackNavigator();

const App = () => {
  const ref = React.useRef();
  const {getInitialState} = useLinking(ref, {
    prefixes: ['deeplink://'],
    config: {
      initialRouteName: 'Home',
      Home: 'Home',
      Details: {
        path: 'Details/:itemId',
        parse: {
          itemId: null,
        },
      },
    },
    getPathFromState(state, config) {
      console.log(state);
    },
  });

  const [isReady, setIsReady] = React.useState(false);
  const [initialState, setInitialState] = React.useState();

  React.useEffect(() => {
    Promise.race([
      getInitialState(),
      new Promise((resolve) => setTimeout(resolve, 150)),
    ])
      .catch((e) => {
        console.error(e);
      })
      .then((state) => {
        if (state !== undefined) {
          setInitialState(state);
        }
        setIsReady(true);
      });
  }, [getInitialState]);

  if (!isReady) {
    return null;
  }
  return (
    <NavigationContainer
      fallback={<Text>Loading...</Text>}
      initialState={initialState}
      ref={ref}>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;

Launched the app using "deeplink://Details/86" in Safari.

1 Answer 1

6

First, update to latest version of @react-navigation/native and then follow the linking docs: https://reactnavigation.org/docs/configuring-links/

Instead of useLinking, you can pass a linking prop to the NavigationContainer component. Then change your config to following:

const App = () => {
  const linking = {
    prefixes: ["deeplink://"],
    config: {
      initialRouteName: "Home",
      screens: {
        Home: {
          path: "home",
        },
        Details: {
          path: "details/:itemId"
        }
      }
    }
  };

  return (
    <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

Then you can open links like deeplink://home or deeplink://details/someid.

Sign up to request clarification or add additional context in comments.

2 Comments

after making the changes you suggested. I got the following error. ExceptionsManager.js:173 The action 'NAVIGATE' with payload {"name":"details","params":{"initial":true,"screen":"65"}} was not handled by any navigator. Do you have a screen named 'details'?"
I don't think its an issue of capitalization If I add the config like this, it works: config: { initialRouteName: 'Home', Home: { path: 'home', }, Details: { path: 'details/:itemId', }, } But then my previous issue still persist. @satya164

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.