This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 55).
Expo Router Link
An Expo Router API that provides Link, Redirect, preview, and zoom transition components.
An Expo Router API that provides components for navigating between routes, including link, redirect, preview, and zoom transitions.
See the Expo Router reference for installation and configuration.
Usage
import { Link } from 'expo-router'; export default function Page() { return <Link href="/about">About</Link>; }
For more information about navigating between routes, read the navigation guide:
Learn how to navigate between pages in Expo Router.
API
import { Link, Redirect } from 'expo-router';
Components
Type: React.Element<LinkProps>
Component that renders a link using href to another route.
By default, it accepts children and wraps them in a <Text> component.
Uses an anchor tag (<a>) on web and performs a client-side navigation to preserve
the state of the website and navigate faster. The web-only attributes such as target,
rel, and download are supported and passed to the anchor tag on web. See
WebAnchorProps for more details.
Note: Client-side navigation works with both single-page apps, and static-rendering.
Example
import { Link } from 'expo-router'; import { View } from 'react-native'; export default function Route() { return ( <View> <Link href="/about">About</Link> </View> ); }
booleanUsed to customize the Link component. It will forward all props to the
first child of the Link. Note that the child component must accept
onPress or onClick props. The href and role are also
passed to the child.
Example
import { Link } from 'expo-router'; import { Pressable, Text } from 'react-native'; export default function Route() { return ( <View> <Link href="/home" asChild> <Pressable> <Text>Home</Text> </Pressable> </Link> </View> ); }
stringOn native, this can be used with CSS interop tools like Nativewind.
On web, this sets the HTML class directly.
SingularOptionsWhen navigating in a Stack, if the target is valid then screens in the history that matches the uniqueness constraint will be removed.
If used with push, the history will be filtered even if no navigation occurs.
booleanWhile in a stack, this will dismiss screens until the provided href is reached. If the href is not found,
it will instead replace the current screen with the provided href.
Example
import { Link } from 'expo-router'; import { View } from 'react-native'; export default function Route() { return ( <View> <Link dismissTo href="/feed">Close modal</Link> </View> ); }
unionThe path of the route to navigate to. It can either be:
- string: A full path like
/profile/settingsor a relative path like../settings. - object: An object with a
pathnameand optionalparams. Thepathnamecan be a full path like/profile/settingsor a relative path like../settings. The params can be an object of key-value pairs.
Example
import { Link } from 'expo-router'; import { View } from 'react-native'; export default function Route() { return ( <View> <Link href="/about">About</Link> <Link href={{ pathname: '/user/[id]', params: { id: 'bacon' } }}> View user </Link> </View> ); }
Acceptable values are: string | HrefObject
(event: MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent) => voidThis function is called on press. Text intrinsically supports press handling with a default highlight state (which can be disabled with suppressHighlighting).
booleanPrefetches the route when the component is rendered on a focused screen.
booleanAlways pushes a new route, and never pops or replaces to existing route. You can push the current route multiple times or with new parameters.
Example
import { Link } from 'expo-router'; import { View } from 'react-native'; export default function Route() { return ( <View> <Link push href="/feed">Login</Link> </View> ); }
Ref<Text>booleanRelative URL references are either relative to the directory or the document. By default, relative paths are relative to the document.
booleanRemoves the current route from the history and replace it with the specified URL. This is useful for redirects.
Example
import { Link } from 'expo-router'; import { View } from 'react-native'; export default function Route() { return ( <View> <Link replace href="/feed">Login</Link> </View> ); }
booleanReplaces the initial screen with the current route.
Inherited Props
Omit<TextProps, 'href'>WebAnchorProps
Type: React.Element<RedirectProps>
Redirects to the href as soon as the component is mounted.
Example
import { View, Text } from 'react-native'; import { Redirect } from 'expo-router'; export default function Page() { const { user } = useAuth(); if (!user) { return <Redirect href="/login" />; } return ( <View> <Text>Welcome Back!</Text> </View> ); }
HrefThe path of the route to navigate to. It can either be:
- string: A full path like
/profile/settingsor a relative path like../settings. - object: An object with a
pathnameand optionalparams. Thepathnamecan be a full path like/profile/settingsor a relative path like../settings. The params can be an object of key-value pairs.
Example
import { Redirect } from 'expo-router'; export default function RedirectToAbout() { return ( <Redirect href="/about" /> ); }
booleanRelative URL references are either relative to the directory or the document. By default, relative paths are relative to the document.
Type: React.Element<LinkAppleZoomProps>
When this component is used inside a Link, zoom transition will be used when navigating to the link's href.
Type: React.Iterable<{
children: ReactNode
}>
Defines the target for an Apple zoom transition.
Example
import { Link } from 'expo-router'; export default function Screen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Link.AppleZoomTarget> <Image source={require('../assets/image.png')} style={{ width: 200, height: 200 }} /> </Link.AppleZoomTarget> </View> ); }
Type: React.Element<LinkMenuProps>
Groups context menu actions for a link.
If multiple Link.Menu components are used within a single Link, only the first will be rendered.
Only Link.MenuAction and Link.Menu components are allowed as children.
Example
<Link.Menu> <Link.MenuAction title="Action 1" onPress={() => {}} /> <Link.MenuAction title="Action 2" onPress={() => {}} /> </Link.Menu>
ReactNodebooleanIf true, the menu item will be displayed as destructive.
See: Apple documentation for more information.
stringThe preferred size of the menu elements.
elementSize property is ignored when palette is used.
See: Apple documentation for more information.
Acceptable values are: 'small' | 'auto' | 'medium' | 'large'
unionCustom image loaded using useImage() hook from expo-image.
Takes priority over icon (SF Symbol) when both are provided.
Example
import { useImage } from 'expo-image'; import { Link } from 'expo-router'; const customIcon = useImage('https://simpleicons.org/icons/expo.svg', { maxWidth: 24, maxHeight: 24, }); <Link.Menu image={customIcon} title="Menu"> <Link.MenuAction title="Action" onPress={() => {}} /> </Link.Menu>
Acceptable values are: ImageRef | null
booleanIf true, the menu will be displayed inline.
This means that the menu will not be collapsed
See: Apple documentation for more information.
booleanIf true, the menu will be displayed as a palette.
This means that the menu will be displayed as one row.
The elementSize property is ignored when palette is used, all items will be elementSize="small". Use elementSize="medium" instead of palette to display actions with titles horizontally.
Note: Palette menus are only supported in submenus.
See: Apple documentation for more information.
stringAn optional subtitle for the submenu. Does not appear on inline menus.
See: Apple documentation for more information.
Type: React.Element<LinkMenuActionProps>
This component renders a context menu action for a link.
It should only be used as a child of Link.Menu or LinkMenu.
booleanIf true, the menu item will be displayed as destructive.
See: Apple documentation for more information.
booleanIf true, the menu item will be disabled and not selectable.
See: Apple documentation for more information.
stringAn elaborated title that explains the purpose of the action.
boolean • Default: falseWhether the menu element should be hidden.
See: Apple documentation for more information.
unionCustom image loaded using useImage() hook from expo-image.
Takes priority over icon (SF Symbol) when both are provided.
Example
import { useImage } from 'expo-image'; import { Link } from 'expo-router'; const customIcon = useImage('https://simpleicons.org/icons/expo.svg', { maxWidth: 24, maxHeight: 24, }); <Link.Menu title="Menu"> <Link.MenuAction image={customIcon} title="Action" onPress={() => {}} /> </Link.Menu>
Acceptable values are: ImageRef | null
stringControls how image-based icons are rendered on iOS.
'template': iOS applies tint color to the icon'original': Preserves original icon colors
See: Apple documentation for more information.
Acceptable values are: 'template' | 'original'
stringAn optional subtitle for the menu item.
See: Apple documentation for more information.
Deprecated: Use
childrenprop instead.
stringThe title of the menu item.
booleanIf true, the menu will be kept presented after the action is selected.
This is marked as unstable, because when action is selected it will recreate the menu, which will close all opened submenus and reset the scroll position.
See: Apple documentation for more information.
Type: React.Element<LinkPreviewProps>
A component used to render and customize the link preview.
If Link.Preview is used without any props, it will render a preview of the href passed to the Link.
If multiple Link.Preview components are used within a single Link, only the first one will be rendered.
To customize the preview, you can pass custom content as children.
Example
<Link href="/about"> <Link.Preview> <Text>Custom Preview Content</Text> </Link.Preview> </Link>
Example
<Link href="/about"> <Link.Preview /> </Link>
ReactNodeType: React.Iterable<LinkTriggerProps>
Serves as the trigger for a link. The content inside this component will be rendered as part of the base link.
If multiple Link.Trigger components are used within a single Link, only the first will be rendered.
Example
<Link href="/about"> <Link.Trigger> Trigger </Link.Trigger> </Link>
booleanA shorthand for enabling the Apple Zoom Transition on this link trigger.
When set to true, the trigger will be wrapped with Link.AppleZoom.
If another Link.AppleZoom is already used inside Link.Trigger, an error
will be thrown.
Hooks
Hook to determine if the current route is rendered inside a preview.
boolean- True if the current route is rendered inside a preview, false otherwise.
| Parameter | Type |
|---|---|
| _options(optional) | UsePreventZoomTransitionDismissalOptions |
Limits the screen area where interactive dismissal gestures are allowed for zoom transitions.
This hook must be called from the destination screen of a zoom transition (the screen you navigate to, not the source). It restricts where app users can start swipe gestures to dismiss the screen and return to the previous screen.
When a dismissal gesture starts inside the bounds, the screen can be dismissed. When a dismissal gesture starts outside the bounds, dismissal is blocked completely. Undefined coordinates place no restriction on that dimension.
Note: Only one instance of this hook should be used per screen. If multiple instances exist, the last one to render will take effect.
voidExample
// In your destination screen (e.g., app/image.tsx) import { usePreventZoomTransitionDismissal } from 'expo-router'; import { useWindowDimensions } from 'react-native'; import { Image } from 'expo-image'; export default function ImageScreen() { const dimensions = useWindowDimensions(); // Only allow dismissal from the bottom 200px of the screen usePreventZoomTransitionDismissal({ unstable_dismissalBoundsRect: { minY: dimensions.height - 200 } }); return <Image source={...} style={{ flex: 1 }} />; }
Interfaces
Defines the screen bounds where interactive dismissal gestures are allowed for zoom transitions.
| Property | Type | Description |
|---|---|---|
| maxX(optional) | number | Maximum X coordinate (right edge) where dismissal gestures are allowed. |
| maxY(optional) | number | Maximum Y coordinate (bottom edge) where dismissal gestures are allowed. |
| minX(optional) | number | Minimum X coordinate (left edge) where dismissal gestures are allowed. |
| minY(optional) | number | Minimum Y coordinate (top edge) where dismissal gestures are allowed. |
| Property | Type | Description |
|---|---|---|
| unstable_dismissalBoundsRect(optional) | DismissalBoundsRect | Defines the screen bounds where interactive dismissal gestures are allowed. Each coordinate is optional. Undefined coordinates place no restriction on that dimension.
For example, if only
|
Types
| Property | Type | Description |
|---|---|---|
| download(optional) | string | Specifies that the The value of the Example
|
| rel(optional) | string | Specifies the relationship between the Common values:
The This property is passed to the underlying anchor ( Example
|
| target(optional) | '_self' | '_blank' | '_parent' | '_top' | string & object | Specifies where to open the
This property is passed to the underlying anchor ( Default: '_self'Example
|