Reference version

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

Expo Router

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

Android
iOS
tvOS
Web
Included in Expo Go

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.

Expo Router guides

Learn about Expo Router basics, navigation patterns, core concepts, and more.

Installation

To use Expo Router in your project, you need to install. Follow the instructions from the Expo Router's installation guide:

Install Expo Router

Learn how to install Expo Router in your project.

Configuration in app config

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

Example app.json with config plugin

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

Configurable properties

NameDefaultDescription
root"app"

Changes the routes directory from app to another value. Avoid using this property unless you have a specific need.

originundefined

Production origin URL where assets in the public folder are hosted. The fetch function is polyfilled to support relative requests from this origin in production. The development origin is inferred using the Expo CLI development server.

headOriginundefined

A more specific origin URL used in the expo-router/head module for iOS handoff. Defaults to origin.

asyncRoutesundefined

Enable async routes (lazy loading). Can be a boolean, a string ("development" or "production"), or an object with platform-specific values ({ android, ios, web, default }). production is currently web-only and will be disabled on native.

platformRoutestrue

Enable or disable platform-specific routes (for example, index.android.tsx and index.ios.tsx).

sitemaptrue

Enable or disable the automatically generated sitemap at /_sitemap.

partialRouteTypestrue

Enable partial typed routes generation. This allows TypeScript to provide type checking for routes without requiring all routes to be statically known.

redirectsundefined

An array of static redirect rules. Each rule should have source, destination, and optionally permanent (defaults to false) and methods (HTTP methods to redirect).

rewritesundefined

An array of static rewrite rules. Each rule should have source, destination, and optionally methods (HTTP methods to rewrite).

headersundefined

A list of headers that are set on every route response from the server. The value can be a string or an array of strings.

disableSynchronousScreensUpdatesfalse

Disable synchronous layout updates for native screens. This can help with performance in some cases.

unstable_useServerMiddlewarefalse
Experimental

Enable server middleware support with a +middleware.ts file. Requires web.output: "server" to be set in app config.

unstable_useServerDataLoadersfalse
Experimental

Enable data loader support. This is only supported for web.output: "static" outputs at the moment.

unstable_useServerRenderingfalse
Experimental

Enable server-side rendering. When enabled with web.output: "server", HTML is rendered at request time instead of being pre-rendered at build time.

Usage

For information core concepts, notation patterns, navigation layouts, and common navigation patterns, start with Router 101 section:

Router 101

APIs

APIDescription
StackStack navigator, toolbar, and screen components
LinkLink and Redirect components
ColorPlatform color utilities
Native TabsNative tab navigation
Split ViewSplit view layout
UIHeadless tab components

API

import { useRouter, Tabs, Navigator, Slot } from 'expo-router';

Components

Tabs

Android
iOS
tvOS
Web

Renders a tabs navigator.

Badge

Android
iOS
tvOS
Web

Type: React.Element<BadgeProps>

BadgeProps

ErrorBoundary

Android
iOS
tvOS
Web

Type: React.Element<ErrorBoundaryProps>

Props passed to a page's ErrorBoundary export.

ErrorBoundaryProps

error

Android
iOS
tvOS
Web
Type: Error

The error that was thrown.

retry

Android
iOS
tvOS
Web
Type: () => Promise<void>

A function that will re-render the route component by clearing the error state.

Icon

Android
iOS
tvOS
Web

Type: React.Element<IconProps>

IconProps

Label

Android
iOS
tvOS
Web

Type: React.Element<LabelProps>

LabelProps

Slot

Android
iOS
tvOS
Web

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

Since a custom Navigator will set the NavigatorContext.contextKey to the current _layout, you can use this to determine if you are inside a custom navigator or not.

VectorIcon

Android
iOS
tvOS
Web

Type: React.Element<VectorIconProps<NameT>>

Helper component for loading vector icons.

Prefer using the md and sf props on Icon rather than using this component directly. Only use this component when you need to load a specific icon from a vector icon family.

Example

import { Icon, VectorIcon } from 'expo-router'; import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons'; <Icon src={<VectorIcon family={MaterialCommunityIcons} name="home" />} />

VectorIconProps

family

Android
iOS
tvOS
Web
Type: { getImageSource: (name: NameT, size: number, color: ColorValue) => Promise<ImageSourcePropType | null> }

The family of the vector icon.

Example

import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';

name

Android
iOS
tvOS
Web
Type: NameT

The name of the vector icon.

Tabs.Screen

Android
iOS
tvOS
Web

Type: React.Element<ScreenProps<TabsProps, TabNavigationState<ParamListBase>, BottomTabNavigationEventMap>>

Constants

unstable_navigationEvents

Android
iOS
tvOS
Web

Type: { addListener: (eventType: EventType, callback: (event: Payload<EventType>) => void) => () => void, emit: (type: EventType, event: Payload<EventType>) => void, enable: () => void, isEnabled: () => boolean, saveCurrentPathname: () => void, }

Hooks

useFocusEffect(effect, do_not_pass_a_second_prop)

Android
iOS
tvOS
Web
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, I'm focused!"); // Return function is invoked whenever the route gets out of focus. return () => { console.log('This route is now unfocused.'); }; }, []), ); return </>; }

useGlobalSearchParams()

Android
iOS
tvOS
Web

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

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

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

Note: For usage information, see Local versus global search parameters.

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>; }

useLoaderData()

Android
iOS
tvOS
Web

Returns the result of the loader function for the calling route.

Returns:
LoaderFunctionResult<T>

Example

app/profile/[user].tsx
import { Text } from 'react-native'; import { useLoaderData } from 'expo-router'; export function loader() { return Promise.resolve({ foo: 'bar' }}; } export default function Route() { const data = useLoaderData<typeof loader>(); // { foo: 'bar' } return <Text>Data: {JSON.stringify(data)}</Text>; }

useLocalSearchParams()

Android
iOS
tvOS
Web

Returns the URL parameters for the contextually focused route. 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.

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

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

Note: For usage information, see Local versus global search parameters.

Returns:
RouteParams<TRoute> & TParams

Example

app/profile/[user].tsx
import { Text } from 'react-native'; import { useLocalSearchParams } from 'expo-router'; export default function Route() { // user=baconbrix & extra=info const { user, extra } = useLocalSearchParams(); return <Text>User: {user}</Text>; }

useNavigation(parent)

Android
iOS
tvOS
Web
ParameterTypeDescription
parent(optional)string | HrefObject

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


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

Returns:
T

The navigation object for the current route.

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

Example

app/index.tsx
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.

useNavigationContainerRef()

Android
iOS
tvOS
Web
Returns:
NavigationContainerRefWithCurrent<RootParamList>

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

usePathname()

Android
iOS
tvOS
Web

Returns the currently selected route location without search parameters. For example, /acme?foo=bar returns /acme. Segments will be normalized. For example, /[id]?id=normal becomes /normal.

Returns:
string

Example

app/profile/[user].tsx
import { Text } from 'react-native'; import { usePathname } from 'expo-router'; export default function Route() { // pathname = "/profile/baconbrix" const pathname = usePathname(); return <Text>Pathname: {pathname}</Text>; }

Deprecated: Use useNavigationContainerRef instead, which returns a React ref.

useRootNavigation()

Android
iOS
tvOS
Web

useRootNavigationState()

Android
iOS
tvOS
Web

Returns the navigation state of the navigator which contains the current screen.

Returns:
Readonly<undefined>

Example

import { useRootNavigationState } from 'expo-router'; export default function Route() { const { routes } = useRootNavigationState(); return <Text>{routes[0].name}</Text>; }

useRouter()

Android
iOS
tvOS
Web

Returns the Router object for imperative navigation.

Returns:
Router

Example

import { useRouter } from 'expo-router'; import { Text } from 'react-native'; export default function Route() { const router = useRouter(); return ( <Text onPress={() => router.push('/home')}>Go Home</Text> ); }

useSegments()

Android
iOS
tvOS
Web

Returns 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 becomes ["[id]"].

Returns:
RouteSegments<TSegments>

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:

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

This can be strictly typed using the following abstract with useSegments hook:

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

useSitemap()

Android
iOS
tvOS
Web
Returns:
SitemapType | null

Methods

Sitemap()

Android
iOS
tvOS
Web
Returns:
Element

withLayoutContext(Nav, processor, useOnlyUserDefinedScreens)

Android
iOS
tvOS
Web
ParameterTypeDescription
NavT

The navigator component to wrap.

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

A function that processes the screens before passing them to the navigator.

useOnlyUserDefinedScreens(optional)boolean

If true, all screens not specified as navigator's children will be ignored.

Default:false

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

Enables use of other built-in React Navigation navigators and other navigators built with the React Navigation custom navigator API.

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

Example

app/_layout.tsx
import { ParamListBase, TabNavigationState } from "@react-navigation/native"; import { createMaterialTopTabNavigator, MaterialTopTabNavigationOptions, MaterialTopTabNavigationEventMap, } from "@react-navigation/material-top-tabs"; import { withLayoutContext } from "expo-router"; const MaterialTopTabs = createMaterialTopTabNavigator(); const ExpoRouterMaterialTopTabs = withLayoutContext< MaterialTopTabNavigationOptions, typeof MaterialTopTabs.Navigator, TabNavigationState<ParamListBase>, MaterialTopTabNavigationEventMap >(MaterialTopTabs.Navigator); export default function TabLayout() { return <ExpoRouterMaterialTopTabs />; }

Types

EffectCallback()

Android
iOS
tvOS
Web

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

Returns:

undefined | void | () => void

ExternalPathString

Android
iOS
tvOS
Web

Literal Type: union

Acceptable values are: {string}:{string} | //{string}

Href<T>

Android
iOS
tvOS
Web

The main routing type for Expo Router. It includes all available routes with strongly typed parameters. It can either be:

  • string: A full path like /profile/settings or a relative path like ../settings.
  • object: An object with a pathname and optional params. The pathname can be a full path like /profile/settings or a relative path like ../settings. The params can be an object of key-value pairs.

An Href can either be a string or an object.

Generic: T

Type: T ? T[href] : string | HrefObject

HrefObject

Android
iOS
tvOS
Web
PropertyTypeDescription
params(optional)UnknownInputParams

Optional parameters for the route.

pathnamestring

The path of the route.

NativeIntent

Android
iOS
tvOS
Web

Created by using a special file called +native-intent.tsx at the top-level of your project's app directory. It exports redirectSystemPath or legacy_subscribe functions, both methods designed to handle URL/path processing.

Useful for re-writing URLs to correctly target a route when unique/referred URLs are incoming from third-party providers or stale URLs from previous versions.

See: For more information on how to use NativeIntent, see Customizing links.

PropertyTypeDescription
legacy_subscribe(optional)(listener: (url: string) => void) => undefined | void | () => void
Experimentally available in SDK 52.

Useful as an alternative API when a third-party provider doesn't support Expo Router but has support for React Navigation via Linking.subscribe() for existing projects.

Using this API is not recommended for newer projects or integrations since it is incompatible with Server Side Routing and Static Rendering, and can become challenging to manage while offline or in a low network environment.

redirectSystemPath(optional)(event: { initial: boolean, path: string }) => Promise<string | null> | string | null

A special method used to process URLs in native apps. When invoked, it receives an options object with the following properties:

  • path: represents the URL or path undergoing processing.
  • initial: a boolean indicating whether the path is the app's initial URL.

Its return value should be a string, a Promise<string | null>, or null. When a falsy value is returned (for example, null), no redirection occurs and the app stays on the current path.

Note that throwing errors within this method may result in app crashes. It's recommended to wrap your code inside a try/catch block and utilize .catch() when appropriate.

See: For usage information, see Redirecting system paths.

PickPartial

Android
iOS
tvOS
Web

Literal Type: union

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

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

RedirectConfig

Android
iOS
tvOS
Web
PropertyTypeDescription
destinationstring
-
destinationContextKeystring
-
external(optional)boolean
-
methods(optional)string[]
-
permanent(optional)boolean
-
sourcestring
-

RelativePathString

Android
iOS
tvOS
Web

Literal Type: union

Acceptable values are: ./{string} | ../{string} | '..'

ResultState

Android
iOS
tvOS
Web

Type: PartialState<NavigationState> extended by:

PropertyTypeDescription
state(optional)ResultState
-

Route

Android
iOS
tvOS
Web

Type: Exclude<Extract[pathname], RelativePathString | ExternalPathString>

Router

Android
iOS
tvOS
Web

Returns router object for imperative navigation API.

Example

import { router } from 'expo-router'; import { Text } from 'react-native'; export default function Route() { return ( <Text onPress={() => router.push('/home')}>Go Home</Text> ); }
PropertyTypeDescription
back() => void

Goes back in the navigation history.

canDismiss() => boolean

Checks if it is possible to dismiss the current screen. Returns true if the router is within the stack with more than one screen in stack's history.

canGoBack() => boolean

Navigates to a route in the navigator's history if it supports invoking the back function.

dismiss(count: number) => void

Navigates to the a stack lower than the current screen using the provided count if possible, otherwise 1.

If the current screen is the only route, it will dismiss the entire stack.

dismissAll() => void

Returns to the first screen in the closest stack. This is similar to popToTop stack action.

dismissTo(href: Href, options: NavigationOptions) => void

Dismisses screens until the provided href is reached. If the href is not found, it will instead replace the current screen with the provided href.

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

Navigates to the provided href.

prefetch(name: Href) => void

Prefetch a screen in the background before navigating to it

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

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

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

Navigates to route without appending to the history. Can be used with useFocusEffect to redirect imperatively to a new screen.

See: Using useRouter() hook to redirect.

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

Updates the current route's query params.

ScreenProps

Android
iOS
tvOS
Web
PropertyTypeDescription
dangerouslySingular(optional)SingularOptions
-
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.

SearchOrHash

Android
iOS
tvOS
Web

Literal Type: union

Acceptable values are: ?{string} | #{string}

SingularOptions

Android
iOS
tvOS
Web

Type: boolean or object shaped as below:

(name, params) => string | undefined

ParameterTypeDescription
name(index signature)string
-
params(index signature)UnknownOutputParams
-

SitemapType

Android
iOS
tvOS
Web
PropertyTypeDescription
childrenSitemapType[]
-
contextKeystring
-
filenamestring
-
hrefstring | Href
-
isGeneratedboolean
-
isInitialboolean
-
isInternalboolean
-