React Navigation Linking not working with conditional stack rendering

Viewed 261

I am making a expo (react-native) project and use React Navigation.

I use conditional stack rendering based on if the user is logged in to my app. I also need to use deep linking to connect to my app and open specific screens. When I run my app with the url from a cold start it works great, but if the app is already started and I use a deep linking, it doesn't work (the screen doesn't change).

here is my code:

import React, { useState, useEffect } from "react";
import { NavigationContainer } from "@react-navigation/native";
import * as Linking from "expo-linking";

import useStore from "../Store";
import AuthStack from "./AuthStack";
import AppTabs from "./AppTabs";

const prefix = Linking.createURL("/");

export default function Routes() {
  const [data, setData] = useState();

// These are screens for the AuthStack only

  const linking = {
    prefixes: [prefix],
    config: {
      screens: {
        Login: "login",
        Register: "register",
        EmailValidation: "emailvalidation",
      },
    },
  };

  const handleDeepLink = (event) => {
    const eventData = Linking.parse(event.url);
    setData(eventData);
  };

  useEffect(() => {
    const getInitialUrl = async () => {
      const initialURL = await Linking.getInitialURL();
      if (initialURL) {
        setData(Linking.parse(initialURL));
      }
    };

    Linking.addEventListener("url", handleDeepLink);
    if (!data) {
      getInitialUrl();
    }
    return () => {
      Linking.removeEventListener("url", handleDeepLink);
    };
  }, []);

// Assuming the user variable is set to null or false

  return (
    <NavigationContainer linking={linking}>
      {user ? <AppTabs /> : <AuthStack />}
    </NavigationContainer>
  );
}

Here is the auth stack screen:

import React from "react";
import { createStackNavigator } from "@react-navigation/stack";

import Login from "../Screens/Login";
import Register from "../Screens/Register";
import EmailValidation from "../Screens/EmailValidation";

const Stack = createStackNavigator();

export default function AuthStack() {
  return (
    <Stack.Navigator
      screenOptions={{
        header: () => null,
      }}
      initialRouteName="Login"
    >
      <Stack.Screen name="Login" component={Login} />
      <Stack.Screen name="Register" component={Register} />
      <Stack.Screen name="EmailValidation" component={EmailValidation} />
    </Stack.Navigator>
  );
}

Thanks for reading and ask me if you need more information/specification.

1 Answers

I think you forgot importing the data variable on the useEffect array deps, so the value of data isn't been updated properly

useEffect(() => {
    const getInitialUrl = async () => {
      const initialURL = await Linking.getInitialURL();
      if (initialURL) {
        setData(Linking.parse(initialURL));
      }
    };

    Linking.addEventListener("url", handleDeepLink);
    if (!data) {
      getInitialUrl();
    }
    return () => {
      Linking.removeEventListener("url", handleDeepLink);
    };
  }, [data]);
Related