React Native integration for React Navigation providing navigation containers, deep linking, and platform-specific navigation behaviors.
—
Deep linking enables navigation to specific screens in your app using URLs. React Navigation provides comprehensive URL-based navigation with path matching, prefixes, and state synchronization.
Configure deep linking behavior through the NavigationContainer's linking prop.
interface LinkingOptions<ParamList extends {}> {
/** Whether deep link handling should be enabled. Defaults to true when linking options are provided */
enabled?: boolean;
/** URL prefixes to match against. Stripped from URLs before parsing */
prefixes: string[];
/** Optional function to filter which URLs should be handled */
filter?: (url: string) => boolean;
/** Path configuration for mapping URLs to navigation state */
config?: {
/** Root path for the entire navigation tree */
path?: string;
/** Screen path configurations */
screens: PathConfigMap<ParamList>;
/** Name of the initial route for the root navigator */
initialRouteName?: keyof ParamList;
};
/** Custom function to get the initial URL. Defaults to Linking.getInitialURL() */
getInitialURL?: () => string | null | undefined | Promise<string | null | undefined>;
/** Custom function to subscribe to URL updates */
subscribe?: (listener: (url: string) => void) => undefined | void | (() => void);
/** Custom function to parse URL to navigation state */
getStateFromPath?: typeof getStateFromPath;
/** Custom function to convert navigation state to URL */
getPathFromState?: typeof getPathFromState;
/** Custom function to convert navigation state to action */
getActionFromState?: typeof getActionFromState;
}
type PathConfigMap<ParamList> = {
[RouteName in keyof ParamList]: string | PathConfig<ParamList[RouteName]>;
};
interface PathConfig<ParamList> {
path?: string;
exact?: boolean;
screens?: PathConfigMap<ParamList>;
initialRouteName?: keyof ParamList;
parse?: { [Param in keyof ParamList]?: (value: string) => ParamList[Param] };
stringify?: { [Param in keyof ParamList]?: (value: ParamList[Param]) => string };
}Usage Examples:
import { NavigationContainer } from '@react-navigation/native';
// Basic deep linking setup
const linking = {
prefixes: ['myapp://'],
config: {
screens: {
Home: 'home',
Profile: 'profile/:id',
Settings: 'settings',
},
},
};
function App() {
return (
<NavigationContainer linking={linking}>
{/* Your navigators */}
</NavigationContainer>
);
}
// Advanced configuration with nested navigators
const advancedLinking = {
prefixes: ['myapp://', 'https://myapp.com'],
config: {
screens: {
Auth: {
screens: {
Login: 'login',
Register: 'register',
},
},
Main: {
screens: {
Home: 'home',
Profile: {
path: 'profile/:id',
parse: {
id: (id: string) => parseInt(id, 10),
},
},
Settings: {
path: 'settings',
screens: {
Account: 'account',
Privacy: 'privacy',
},
},
},
},
},
},
};
// With URL filtering
const filteredLinking = {
prefixes: ['myapp://'],
filter: (url: string) => !url.includes('oauth-callback'),
config: {
screens: {
Home: 'home',
Profile: 'profile/:id',
},
},
};Define which URL schemes and hosts your app should handle.
interface LinkingOptions<ParamList> {
/**
* The prefixes are stripped from the URL before parsing them.
* Usually they are the scheme + host (e.g. myapp://chat?user=jane)
* This is not supported on Web.
*/
prefixes: string[];
}Usage Examples:
// App-specific scheme
const linking = {
prefixes: ['myapp://'],
// myapp://profile/123 -> profile/123
};
// Universal links
const universalLinking = {
prefixes: ['https://example.com'],
// https://example.com/profile/123 -> profile/123
};
// Multiple prefixes with wildcards
const multiPrefixLinking = {
prefixes: [
'myapp://',
'https://example.com',
'https://*.example.com', // Matches any subdomain
],
};
// Development and production
const environmentLinking = {
prefixes: [
'myapp://',
__DEV__
? 'https://dev.example.com'
: 'https://example.com',
],
};Map URL paths to navigation screens with parameter parsing.
interface PathConfig<ParamList> {
/** Path pattern to match (e.g., 'profile/:id') */
path?: string;
/** Whether the path should match exactly */
exact?: boolean;
/** Nested screen configurations */
screens?: PathConfigMap<ParamList>;
/** Initial route name for nested navigators */
initialRouteName?: keyof ParamList;
/** Functions to parse URL parameters */
parse?: { [Param in keyof ParamList]?: (value: string) => ParamList[Param] };
/** Functions to stringify parameters for URL generation */
stringify?: { [Param in keyof ParamList]?: (value: ParamList[Param]) => string };
}Usage Examples:
// Simple path mapping
const config = {
screens: {
Home: 'home',
About: 'about',
Contact: 'contact',
},
};
// Paths with parameters
const paramsConfig = {
screens: {
Profile: 'profile/:id',
Article: 'article/:slug',
Category: 'category/:name/page/:page',
},
};
// Parameter parsing and validation
const parsedConfig = {
screens: {
Profile: {
path: 'profile/:id',
parse: {
id: (id: string) => {
const parsed = parseInt(id, 10);
return isNaN(parsed) ? 0 : parsed;
},
},
},
Search: {
path: 'search',
parse: {
q: (query: string) => decodeURIComponent(query),
page: (page: string) => Math.max(1, parseInt(page, 10)),
},
},
},
};
// Nested navigator configuration
const nestedConfig = {
screens: {
Home: 'home',
Shop: {
path: 'shop',
screens: {
ProductList: 'products',
ProductDetail: 'product/:id',
Cart: 'cart',
Checkout: {
path: 'checkout',
screens: {
Shipping: 'shipping',
Payment: 'payment',
Confirmation: 'confirmation',
},
},
},
},
},
};Control which URLs should be handled by your navigation system.
interface LinkingOptions<ParamList> {
/**
* Optional function which takes an incoming URL and returns a boolean
* indicating whether React Navigation should handle it.
* This can be used to disable deep linking for specific URLs.
*/
filter?: (url: string) => boolean;
}Usage Examples:
// Filter out authentication callbacks
const authFilterLinking = {
prefixes: ['myapp://'],
filter: (url: string) => !url.includes('oauth-callback'),
config: {
screens: {
Home: 'home',
Profile: 'profile/:id',
},
},
};
// Filter based on URL patterns
const patternFilterLinking = {
prefixes: ['myapp://'],
filter: (url: string) => {
// Don't handle admin URLs
if (url.includes('/admin/')) return false;
// Don't handle external redirects
if (url.includes('redirect=')) return false;
// Handle everything else
return true;
},
};Implement custom logic for URL processing and state management.
interface LinkingOptions<ParamList> {
/** Custom function to get the initial URL used for linking */
getInitialURL?: () => string | null | undefined | Promise<string | null | undefined>;
/** Custom function to subscribe to URL updates */
subscribe?: (listener: (url: string) => void) => undefined | void | (() => void);
/** Custom function to parse URL to navigation state (advanced) */
getStateFromPath?: typeof getStateFromPath;
/** Custom function to convert state to URL (advanced) */
getPathFromState?: typeof getPathFromState;
/** Custom function to convert state to action (advanced) */
getActionFromState?: typeof getActionFromState;
}Usage Examples:
import { Linking } from 'react-native';
// Custom initial URL handling
const customInitialURL = {
prefixes: ['myapp://'],
getInitialURL: async () => {
// Check if app was opened from a deep link
const url = await Linking.getInitialURL();
// Custom logic for handling the initial URL
if (url?.includes('special-link')) {
// Transform or validate the URL
return url.replace('special-link', 'normal-link');
}
return url;
},
};
// Custom URL subscription
const customSubscription = {
prefixes: ['myapp://'],
subscribe: (listener: (url: string) => void) => {
// Custom URL change handling
const onReceiveURL = ({ url }: { url: string }) => {
// Apply custom transformations or filtering
if (url.includes('valid-prefix')) {
listener(url);
}
};
const subscription = Linking.addEventListener('url', onReceiveURL);
return () => subscription?.remove();
},
};
// Custom state parsing
const customStateParsing = {
prefixes: ['myapp://'],
getStateFromPath: (path: string, config: any) => {
// Custom logic to convert path to navigation state
if (path.startsWith('/legacy/')) {
// Handle legacy URL format
const newPath = path.replace('/legacy/', '/');
return getStateFromPath(newPath, config);
}
// Use default parsing for other paths
return getStateFromPath(path, config);
},
};Handle cases where deep links cannot be processed or lead to invalid states.
// Invalid URLs that don't match any configured path will be ignored
// Use NavigationContainer's onUnhandledAction prop to handle edge cases
function App() {
const handleUnhandledAction = (action: NavigationAction) => {
console.warn('Unhandled navigation action:', action);
// Custom error handling or fallback navigation
};
return (
<NavigationContainer
linking={linking}
onUnhandledAction={handleUnhandledAction}
>
{/* Your navigators */}
</NavigationContainer>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-navigation--native