Search code examples
react-nativeemailwebviewios-simulatordeep-linking

React Native WebView Not Opening from Email Deep Link in Simulator


Unable to Open React Native WebView Using Deep Link from Email in iOS Simulator

I'm developing a React Native app with a WebView that should display a password reset page. This page is hosted locally during development http://localhost:3000/reset-password. The goal is to open this WebView in my app when a user clicks on a deep link in an email. The email is sent to the user whenever he tries to set his password. I did this using AWS and the link that is sent to the user to reset the password is the following:

link:http://localhost:3000/reset-password?token=${jwt.sign({ data: userMatch }, config.app.secret, {expiresIn: "1h", algorithm: <jwt.Algorithm>config.app.algorithm})}

What Works

The WebView loads correctly when I manually navigate to it within the app. Communication between my web content and React Native component is functional; I can navigate back to the Login screen from the WebView.

What Doesn't Work

When clicking the deep link from an email, the link opens in the browser outside of my app instead of navigating to the WebView within the app.

My DeepLinking Configuration is found in App.tsx

const linking = {
  prefixes:["localhost:3000","yourapp://"],
  config:{
    screens:{
      // Reset:"reset-password",
      Local:"reset-password"
    }
  }
}

const App = () => {
  const [initialURL, setInitialURL] = useState(null);
  useEffect(() => {
    Linking.getInitialURL().then((url:any) => {
      if (url) {
        setInitialURL(url);
      }
    });
  }, []);

  return (
    <>
    <QueryClientProvider client={queryClient}>
    <StatusBar  backgroundColor="white" barStyle="dark-content" ></StatusBar>
    <NavigationContainer linking={linking}>
     <Stack.Navigator initialRouteName='Login' screenOptions={{ headerStyle :{
      backgroundColor: 'white',
    }}}>
    <Stack.Screen name="Login" component={LoginScreen} initialParams={{ initialURL }} options={{headerShown:false}} />
    <Stack.Screen name="Home" component={MyTabs} options={{ headerShown: false}}/> 
    <Stack.Screen name="Reset" component={ResetPasswordScreen} options={{headerShown:false}}/>
    <Stack.Screen name="Local" component={LocalWebViewScreen} options={{headerShown:false}} />
    </Stack.Navigator>
    </NavigationContainer>
    </QueryClientProvider>
  </>
  )
}

const styles= StyleSheet.create({
  container:{
    flex:1,
    backgroundColor:'#121212',
  }
})

export default App;

/// And this is the LocalWebviewComponent that renders my react web page running on localhost:3000

LocalWebview.tsx

const LocalWebViewScreen = ({route}:any) => {
    const navigation = useNavigation<StackNavigationProp<RootStackParamList>>();
    const webViewRef = useRef(null);

    const handleMessage = (event:any) => {
        const message = event.nativeEvent.data
        if(message === "navigateBack"){
            console.warn("they are communicating")
            navigation.navigate("Login")
        }
    }
    const token = route.params?.jwt 
    const url = `http://localhost:3000/reset-password?token=${token}`;
  return (
  <WebView
    javaScriptEnabled={true}
    domStorageEnabled={true}
    startInLoadingState={true}
    ref={webViewRef}
    source={{ uri: url }} 
    onMessage={handleMessage}
   />
  );
};

export default LocalWebViewScreen;


Solution

  • AFAIK you cannot test deep links on iOS simulator from e2e. If you wanna test if your can handle your link use npx uri-scheme open "exp://127.0.0.1:19000/--/reset-password" --ios

    Docs are here