Reference version

This is documentation for the next SDK version. For up-to-date documentation, see the latest version (SDK 51).

Expo Router

GitHub

npm

A file-based routing library for React Native and web applications.

Android
iOS
Web

expo-router is a routing library for React Native and web apps. It enables navigation management using a file-based routing system and provides native navigation components and is built on top of React Navigation.

Installation

Terminal
- npx expo install expo-router

Configuration in app.json/app.config.js

If you are using the default template to create a new project, expo-router config plugin is configured in the app config automatically.

Example app.json with config plugin

app.json
{
  "expo": {
    "plugins": ["expo-router"]
  }
}

Usage

Find more information and guides about using expo-router in Expo Router section.

API

import { Stack, Tabs, Link } from 'expo-router';

Components

ErrorBoundary

Type: React.Element<ErrorBoundaryProps>

ErrorBoundaryProps

Props passed to a page's ErrorBoundary export.

Android
iOS
Web

error

Type: Error

The error that was thrown.

Android
iOS
Web

retry

Type: () => Promise<void>

Retry rendering the component by clearing the error state.

Link

Type: React.Element<PropsWithChildren<LinkProps<T>>>

Component to render link to another route using a path. Uses an anchor tag on the web.

LinkProps

Android
iOS
Web

asChild

Optional • Type: boolean

Forward props to child component. Useful for custom buttons.

Android
iOS
Web

className

Optional • Type: string

On web, this sets the HTML class directly. On native, this can be used with CSS interop tools like Nativewind.

Android
iOS
Web

href

Type: Href<T>

Path to route to.

Android
iOS
Web

onPress

Optional • Type: (e: MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent) => void

This function is called on press. Text intrinsically supports press handling with a default highlight state (which can be disabled with suppressHighlighting).

Android
iOS
Web

push

Optional • Type: boolean

Should push the current route

Android
iOS
Web

relativeToDirectory

Optional • Type: boolean

Relative URL references are either relative to the directory or the document. By default, relative paths are relative to the document.

See: Resolving relative references in Mozilla's documentation

Android
iOS
Web

replace

Optional • Type: boolean

Should replace the current route without adding to the history.

Android
iOS
Web

withAnchor

Optional • Type: boolean

Should this route replace the initial screen

Inherited Props

  • Omit<TextProps, 'href'>
  • WebAnchorProps

Slot

Type: React.Element<Omit<NavigatorProps<any>, 'children'>>

Renders the currently selected content.

There are actually two different implementations of Slot:

  • Used inside a _layout as the Navigator
  • Used inside a Navigator as the content

As a custom <Navigator /> will set the NavigatorContext.contextKey to be the current _layout, we can use this to determine if we are inside a custom navigator or not.

Hooks

Android
iOS
Web

useFocusEffect(effect, do_not_pass_a_second_prop)

ParameterTypeDescription
effectEffectCallback

Memoized callback containing the effect, should optionally return a cleanup function.

do_not_pass_a_second_prop
(optional)
undefined-

Hook to run an effect whenever a route is "focused" Similar to React.useEffect. This can be used to perform side-effects such as fetching data or subscribing to events. The passed callback should be wrapped in React.useCallback to avoid running the effect too often.

Returns:

void

Example

import { useFocusEffect } from 'expo-router';
import { useCallback } from 'react';

export default function Route() {
  useFocusEffect(
    // Callback should be wrapped in `React.useCallback` to avoid running the effect too often.
    useCallback(() => {
      // Invoked whenever the route is focused.
      console.log('Hello')
      }, []);
    );
  return </>;
}
Android
iOS
Web

useGlobalSearchParams()

Get the globally selected query parameters, including dynamic path segments. This function will update even when the route is not focused. Useful for analytics or other background operations that don't draw to the screen.

When querying search params in a stack, opt-towards using useLocalSearchParams as these will only update when the route is focused.

Route URL example: acme://profile/baconbrix?extra=info.

Note: See local versus global search parameters for usage information.

Returns:

RouteParams<TRoute, TParams>

Example

app/profile/[user].tsx
import { Text } from 'react-native';
import { useGlobalSearchParams } from 'expo-router';

export default function Route() {
  // user=baconbrix & extra=info
  const { user, extra } = useGlobalSearchParams();
  return <Text>User: {user}</Text>;
}
Android
iOS
Web

useLocalSearchParams()

Returns the URL parameters for the contextually focused route. e.g. /acme?foo=bar -> { foo: "bar" }. This is useful for stacks where you may push a new screen that changes the query parameters. For dynamic routes, both the route parameters and the search parameters are returned.

To observe updates even when the invoking route is not focused, use useGlobalSearchParams().

Returns:

RouteParams<TRoute, TParams>

See: useGlobalSearchParams

Android
iOS
Web

useNavigation(parent)

ParameterTypeDescription
parent
(optional)
string

Provide an absolute path such as /(root) to the parent route or a relative path like ../../ to the parent route.


Access the underlying React Navigation navigation prop to imperatively access layout-specific functionality like navigation.openDrawer() in a Drawer layout.

Returns:

T

The navigation object for the current route.

Example

import { useNavigation } from 'expo-router';

export default function Route() {
  // Access the current navigation object for the current route.
  const navigation = useNavigation();

  return (
    <View>
      <Text onPress={() => {
        // Open the drawer view.
        navigation.openDrawer();
      }}>
        Open Drawer
      </Text>
    </View>
  );
}

When using nested layouts, you can access higher-order layouts by passing a secondary argument denoting the layout route. For example, /menu/_layout.tsx is nested inside /app/orders/, you can use useNavigation('/orders/menu/').

Example

app/orders/menu/index.tsx
import { useNavigation } from 'expo-router';

export default function MenuRoute() {
  const rootLayout = useNavigation('/');
  const ordersLayout = useNavigation('/orders');

  // Same as the default results of `useNavigation()` when invoked in this route.
  const parentLayout = useNavigation('/orders/menu');
}

If you attempt to access a layout that doesn't exist, an error such as Could not find parent navigation with route "/non-existent" is thrown.

See React Navigation documentation on navigation dependent functions for more information.

Android
iOS
Web

useNavigationContainerRef()

Returns:

NavigationContainerRefWithCurrent<RootParamList>

The root <NavigationContainer /> ref for the app. The ref.current may be null if the <NavigationContainer /> hasn't mounted yet.

Android
iOS
Web

usePathname()

Global selected route location without search parameters. For example, /acme?foo=bar -> /acme. Segments will be normalized: /[id]?id=normal -> /normal.

Returns:

string

Example

app/profile/[user].tsx
import { Text } from 'react-native';
import { useSegments } from 'expo-router';

export default function Route() {
  // segments = ["profile", "[user]"]</b>
  const segments = useSegments();

  return <Text>Hello</Text>;
}

Deprecated Use useNavigationContainerRef instead, which returns a React ref.

Android
iOS
Web

useRootNavigation()

Returns:

null | NavigationContainerRef<RootParamList>

Android
iOS
Web

useRootNavigationState()

Returns:

any

Android
iOS
Web

useRouter()

Returns:

Router

Android
iOS
Web

useSegments()

Get a list of selected file segments for the currently selected route. Segments are not normalized, so they will be the same as the file path. For example: /[id]?id=normal -> ["[id]"].

Example

app/profile/[user].tsx
import { Text } from 'react-native';
import { useSegments } from 'expo-router';

export default function Route() {
  // segments = ["profile", "[user]"]
  const segments = useSegments();

  return <Text>Hello</Text>;
}

useSegments can be typed using an abstract. Consider the following file structure, and strictly typed useSegments function:

- app
  - [user]
    - index.js
    - followers.js
  - settings.js

This can be strictly typed using the following abstract:

const [first, second] = useSegments<['settings'] | ['[user]'] | ['[user]', 'followers']>()

Methods

Android
iOS
Web

Redirect(namedParameters)

ParameterType
namedParameters{ href: Href }

Redirects to the href as soon as the component is mounted.

Returns:

null

Android
iOS
Web

withLayoutContext(Nav, processor)

ParameterType
NavT
processor
(optional)
(options: ScreenProps[]) => ScreenProps[]

Return a navigator that automatically injects matched routes and renders nothing when there are no children. Return type with children prop optional

Returns:

Component<PropsWithoutRef<PickPartial<ComponentProps<T>, 'children'>>> & { Screen: (props: ScreenProps<TOptions, TState, TEventMap>) => null }

Types

Android
iOS
Web

EffectCallback()

Memoized callback containing the effect, should optionally return a cleanup function.

Android
iOS
Web

Href

Type: GeneratedHref<T>

The main routing type for Expo Router. Includes all available routes with strongly typed parameters.

A Href can either be a string or an object.

Href accepts an optional T parameter to correctly type dynamic routes string.

For example: Without the generic the route /folder/[slug] will be typed as /folder/${string}, which is incorrect as /folder/apple/orange would be valid. But by passing desired route as a generic Href<'/folder/apple'>, it will validate against this edge case.

Android
iOS
Web

NativeIntent

NameTypeDescription
legacy_subscribe
(optional)
(listener: (url: string) => void) => undefined | void | () => void-
redirectSystemPath
(optional)
(event: { initial: boolean, path: string }) => Promise<string> | string-
Android
iOS
Web

PickPartial

Literal Type: multiple types

The list of input keys will become optional, everything else will remain the same.

Acceptable values are: Omit<T, K> | Partial<Pick<T, K>>

Android
iOS
Web

ResultState

Type: PartialState<NavigationState> extended by:


NameTypeDescription
state
(optional)
ResultState-
Android
iOS
Web

Router

NameTypeDescription
back() => void

Go back in the history.

canDismiss() => boolean

If there's history that supports invoking the dismiss and dismissAll function.

canGoBack() => boolean

If there's history that supports invoking the back function.

dismiss(count: number) => void

Navigate to a screen with a stack lower than the current screen. Using the provided count if possible, otherwise 1.

dismissAll() => void

Navigate to first screen within the lowest stack.

navigate(href: Href<T>, options: NavigationOptions) => void

Navigate to the provided href.

push(href: Href<T>, options: NavigationOptions) => void

Navigate to the provided href using a push operation if possible.

replace(href: Href<T>, options: NavigationOptions) => void

Navigate to route without appending to the history.

setParams(params: Partial<RouteParamInput<T>>) => void

Update the current route query params.

Android
iOS
Web

ScreenProps

NameTypeDescription
getId
(optional)
({ params }: { params: Record<string, any> }) => string | undefined-
initialParams
(optional)
Record<string, any>-
listeners
(optional)
ScreenListeners<TState, TEventMap> | (prop: { navigation: any, route: RouteProp<ParamListBase, string> }) => ScreenListeners<TState, TEventMap>-
name
(optional)
string

Name is required when used inside a Layout component.

options
(optional)
TOptions | (prop: { navigation: any, route: RouteProp<ParamListBase, string> }) => TOptions-
redirect
(optional)
boolean

Redirect to the nearest sibling route. If all children are redirect={true}, the layout will render null as there are no children to render.

Web

WebAnchorProps

NameTypeDescription
download
(optional)
string

Specifies that the href should be downloaded when the user clicks on the link, instead of navigating to it. It is typically used for links that point to files that the user should download, such as PDFs, images, documents, etc.

The value of the download property, which represents the filename for the downloaded file. This property is passed to the underlying anchor (<a>) tag.

Example
<Link href="/image.jpg" download="my-image.jpg">Download image</Link>
rel
(optional)
string

Specifies the relationship between the href and the current route.

Common values:

  • nofollow: Indicates to search engines that they should not follow the href. This is often used for user-generated content or links that should not influence search engine rankings.
  • noopener: Suggests that the href should not have access to the opening window's window.opener object, which is a security measure to prevent potentially harmful behavior in cases of links that open new tabs or windows.
  • noreferrer: Requests that the browser not send the Referer HTTP header when navigating to the href. This can enhance user privacy.

The rel property is primarily used for informational and instructive purposes, helping browsers and web crawlers make better decisions about how to handle and interpret the links on a web page. It is important to use appropriate rel values to ensure that links behave as intended and adhere to best practices for web development and SEO (Search Engine Optimization).

This property is passed to the underlying anchor (<a>) tag.

Example
<Link href="https://expo.dev" rel="nofollow">Go to Expo</Link>`
target
(optional)
'_self' | '_blank' | '_parent' | '_top' | string & object

Specifies where to open the href.

  • _self: the current tab.
  • _blank: opens in a new tab or window.
  • _parent: opens in the parent browsing context. If no parent, defaults to _self.
  • _top: opens in the highest browsing context ancestor. If no ancestors, defaults to _self.

This property is passed to the underlying anchor (<a>) tag.

Default: '_self'
Example
<Link href="https://expo.dev" target="_blank">Go to Expo in new tab</Link>