WarpLink
SDKsReact Native

Deep Links

Handle deep links in React Native for cold and warm start.

Deep links arrive in two scenarios: cold start (app launched by a link) and warm start (app brought from background by a link). Handle both in your root component.

Basic Setup

import { useEffect } from 'react';
import { WarpLink } from '@warplink/react-native';

function App() {
  useEffect(() => {
    // Warm-start: app already running, new link arrives
    const unsubscribe = WarpLink.onDeepLink((event) => {
      if (event.deepLink) {
        navigateTo(event.deepLink.destination);
      } else if (event.error) {
        console.error('Deep link error:', event.error.message);
      }
    });

    // Cold-start: app launched by a link
    WarpLink.getInitialDeepLink().then((link) => {
      if (link) {
        navigateTo(link.destination);
      }
    });

    return unsubscribe; // Clean up listener on unmount
  }, []);

  return <>{/* Your app */}</>;
}

With React Navigation

import { useEffect } from 'react';
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
import { WarpLink } from '@warplink/react-native';

function App() {
  const navigationRef = useNavigationContainerRef();

  useEffect(() => {
    const unsubscribe = WarpLink.onDeepLink((event) => {
      if (event.deepLink) {
        const url = event.deepLink.deepLinkUrl ?? event.deepLink.destination;
        navigationRef.navigate('Product', { url });
      }
    });

    WarpLink.getInitialDeepLink().then((link) => {
      if (link) {
        const url = link.deepLinkUrl ?? link.destination;
        navigationRef.navigate('Product', { url });
      }
    });

    return unsubscribe;
  }, [navigationRef]);

  return (
    <NavigationContainer ref={navigationRef}>
      {/* Your navigator */}
    </NavigationContainer>
  );
}

Cold Start vs Warm Start

ScenarioAPIWhen
Cold startgetInitialDeepLink()App was not running — launched by tapping a link
Warm startonDeepLink(listener)App was in background — brought to foreground by a link

Both should be set up in the same useEffect to handle all cases.

const link = await WarpLink.handleDeepLink('https://aplnk.to/abc123');
if (link) {
  console.log('Link ID:', link.linkId);
  console.log('Destination:', link.destination);

  // Platform-specific deep link URL
  if (link.deepLinkUrl) {
    navigateToPath(link.deepLinkUrl);
  }

  // Custom parameters
  const productId = link.customParams['product_id'] as string | undefined;
  if (productId) {
    showProduct(productId);
  }
}

Error Handling

import { WarpLinkError, ErrorCodes } from '@warplink/react-native';

try {
  const link = await WarpLink.handleDeepLink(url);
} catch (error) {
  if (error instanceof WarpLinkError) {
    switch (error.code) {
      case ErrorCodes.E_NOT_CONFIGURED:
        console.error('Call configure() first');
        break;
      case ErrorCodes.E_INVALID_URL:
        console.error('Not a WarpLink URL');
        break;
      case ErrorCodes.E_LINK_NOT_FOUND:
        showLinkExpired();
        break;
      case ErrorCodes.E_NETWORK_ERROR:
        showOfflineMessage();
        break;
      default:
        console.error(`[${error.code}] ${error.message}`);
    }
  }
}

Listener Events

The onDeepLink listener receives a discriminated union — exactly one of deepLink or error is present:

WarpLink.onDeepLink((event) => {
  if (event.deepLink) {
    // Success — resolved deep link
    console.log(event.deepLink.destination);
  } else if (event.error) {
    // Error — resolution failed
    console.error(event.error.code, event.error.message);
  }
});

Multiple listeners can be registered simultaneously. Each receives every event. The native event subscription is cleaned up when the last listener is removed.

On this page