File: router-ui.md | Updated: 11/15/2025
Hide navigation
Search
Ctrl K
Home Guides EAS Reference Learn
Reference version
SDK 54
Archive Expo Snack Discord and Forums Newsletter
An Expo Router submodule that provides headless tab components to create custom tab layouts.
Android
iOS
tvOS
Web
Bundled version:
~6.0.14
Copy page
expo-router/ui is a submodule of expo-router library and exports components and hooks to build custom tab layouts, rather than using the default React Navigation
navigators provided by expo-router.
See the Expo Router reference for more information about the file-based routing library for native and web app.
To use expo-router/ui in your project, you need to install expo-router in your project. Follow the instructions from the Expo Router's installation guide:
Install Expo Router
Learn how to install Expo Router in your project.
If you are using the default
template to create a new project, expo-router's config plugin
is already configured in your app config.
app.json
Copy
{ "expo": { "plugins": ["expo-router"] } }
For information about using expo-router/ui in Custom tab layouts guide:
import { Tabs, TabList, TabTrigger, TabSlot } from 'expo-router/ui';
TabContextType: React.[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component) <[ProviderProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#providerprops) <[ExpoTabsNavigatorScreenOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#expotabsnavigatorscreenoptions) >>
TabListType: React.[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component) <[TabListProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tablistprops) >
Wrapper component for TabTriggers. TabTriggers within the TabList define the tabs.
Example
<Tabs> <TabSlot /> <TabList> <TabTrigger name="home" href="/" /> </TabList> </Tabs>
asChildOptional • Type: boolean
Forward props to child component and removes the extra <View>. Useful for custom wrappers.
[ViewProps](https://reactnative.dev/docs/view#props) TabsType: React.[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component) <[TabsProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabsprops) >
Root component for the headless tabs.
See:
useTabsWithChildrenfor a hook version of this component.
Example
<Tabs> <TabSlot /> <TabList> <TabTrigger name="home" href="/" /> </TabList> </Tabs>
asChildOptional • Type: boolean
Forward props to child component and removes the extra <View>. Useful for custom wrappers.
optionsOptional • Type: [UseTabsOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#usetabsoptions)
[ViewProps](https://reactnative.dev/docs/view#props) TabSlotType: React.[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component) <[TabSlotProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabslotprops) >
Renders the current tab.
See:
useTabSlotfor a hook version of this component.
Example
<Tabs> <TabSlot /> <TabList> <TabTrigger name="home" href="/" /> </TabList> </Tabs>
detachInactiveScreensOptional • Type: boolean
Remove inactive screens.
renderFnOptional • Type: defaultTabsSlotRender
Override how the Screen component is rendered.
ComponentProps<ScreenContainer>TabTriggerType: React.[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component) <[TabTriggerProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabtriggerprops) >
Creates a trigger to navigate to a tab. When used as child of TabList, its functionality slightly changes since the href prop is required, and the trigger also defines what routes are present in the Tabs.
When used outside of TabList, this component no longer requires an href.
Example
<Tabs> <TabSlot /> <TabList> <TabTrigger name="home" href="/" /> </TabList> </Tabs>
asChildOptional • Type: boolean
Forward props to child component. Useful for custom wrappers.
hrefOptional • Type: [Href](https://docs.expo.dev/versions/v54.0.0/sdk/router#href-1)
Name of tab. Required when used within a TabList.
nameType: string
Name of tab. When used within a TabList this sets the name of the tab. Otherwise, this references the name.
resetOptional • Literal type: union
Resets the route when switching to a tab.
Acceptable values are: SwitchToOptions[reset] | 'onLongPress'
[PressablePropsWithoutFunctionChildren](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#pressablepropswithoutfunctionchildren) useTabSlotType: React.[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component) <[TabSlotProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabslotprops) >
Returns a ReactElement of the current tab.
Example
function MyTabSlot() { const slot = useTabSlot(); return slot; }
useTabSlot(namedParameters)| Parameter | Type |
| --- | --- |
| namedParameters(optional) | [TabSlotProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabslotprops) |
Returns a ReactElement of the current tab.
Returns:
[Element](https://www.typescriptlang.org/docs/handbook/jsx.html#function-component)
Example
function MyTabSlot() { const slot = useTabSlot(); return slot; }
useTabsWithChildren(options)| Parameter | Type |
| --- | --- |
| options | [UseTabsWithChildrenOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#usetabswithchildrenoptions) |
Hook version of Tabs. The returned NavigationContent component should be rendered. Using the hook requires using the <TabList /> and <TabTrigger /> components exported from Expo Router.
The useTabsWithTriggers() hook can be used for custom components.
See:
Tabsfor the component version of this hook.
Example
export function MyTabs({ children }) { const { NavigationContent } = useTabsWithChildren({ children }) return <NavigationContent /> }
useTabsWithTriggers(options)| Parameter | Type |
| --- | --- |
| options | [UseTabsWithTriggersOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#usetabswithtriggersoptions) |
Alternative hook version of Tabs that uses explicit triggers instead of children.
Returns:
[TabsContextValue](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabscontextvalue)
See:
Tabsfor the component version of this hook.
Example
export function MyTabs({ children }) { const { NavigationContent } = useTabsWithChildren({ triggers: [] }) return <NavigationContent /> }
useTabTrigger(options)| Parameter | Type |
| --- | --- |
| options | [TabTriggerProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabtriggerprops) |
Utility hook creating custom TabTrigger.
Returns:
[UseTabTriggerResult](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#usetabtriggerresult)
ExpoTabsNavigationPropType: [NavigationProp](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#navigationprop) <ParamList, [RouteName](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#routename) , [NavigatorID](https://reactnavigation.org/docs/custom-navigators/#type-checking-navigators) , [TabNavigationState](https://reactnavigation.org/docs/custom-navigators/#type-checking-navigators) <ParamListBase>, [ExpoTabsScreenOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#expotabsscreenoptions) , [TabNavigationEventMap](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabnavigationeventmap) >
ExpoTabsNavigatorOptionsLiteral Type: union
Acceptable values are: [DefaultNavigatorOptions](https://reactnavigation.org/docs/custom-navigators/#type-checking-navigators) <ParamListBase, string | undefined, [TabNavigationState](https://reactnavigation.org/docs/custom-navigators/#type-checking-navigators) <ParamListBase>, [ExpoTabsScreenOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#expotabsscreenoptions) , [TabNavigationEventMap](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabnavigationeventmap) , [ExpoTabsNavigationProp](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#expotabsnavigationprop) <ParamListBase>> | [Omit](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) <[TabRouterOptions](https://reactnavigation.org/docs/custom-navigators/#type-checking-navigators) , 'initialRouteName'> | [ExpoTabsNavigatorScreenOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#expotabsnavigatorscreenoptions)
ExpoTabsNavigatorScreenOptions| Property | Type | Description |
| --- | --- | --- |
| detachInactiveScreens(optional) | boolean | - |
| freezeOnBlur(optional) | boolean | - |
| lazy(optional) | boolean | - |
| unmountOnBlur(optional) | boolean | - |
ExpoTabsResetValueLiteral Type: string
Acceptable values are: 'always' | 'onFocus' | 'never'
ExpoTabsScreenOptionsType: [Pick](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys) <[BottomTabNavigationOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#bottomtabnavigationoptions) , 'title' | 'lazy' | 'freezeOnBlur'> extended by:
| Property | Type | Description |
| --- | --- | --- |
| action | [NavigationAction](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#navigationaction) | - |
| params(optional) | object | - |
| title | string | - |
SwitchToOptionsOptions for switchTab function.
| Property | Type | Description |
| --- | --- | --- |
| reset(optional) | [ExpoTabsResetValue](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#expotabsresetvalue) | Navigate and reset the history. |
TabNavigationEventMap| Property | Type | Description |
| --- | --- | --- |
| tabLongPress | { data: undefined } | Event which fires on long press on the tab in the tab bar. |
| tabPress | { canPreventDefault: true, data: undefined } | Event which fires on tapping on the tab in the tab bar. |
TabsContextValueType: [ReturnType](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#returntype) <useNavigationBuilder>
The React Navigation custom navigator.
See:
useNavigationBuilderhook from React Navigation for more information.
TabsSlotRenderOptionsOptions provided to the UseTabSlotOptions.
| Property | Type | Description |
| --- | --- | --- |
| detachInactiveScreens | boolean | Should the screen be unloaded when inactive. |
| index | number | Index of screen. |
| isFocused | boolean | Whether the screen is focused. |
| loaded | boolean | Whether the screen has been loaded. |
TabTriggerOptions| Property | Type | Description |
| --- | --- | --- |
| href | [Href](https://docs.expo.dev/versions/v54.0.0/sdk/router#href-1) | - |
| name | string | - |
TriggerType: extended by:
| Property | Type | Description |
| --- | --- | --- |
| isFocused | boolean | - |
| resolvedHref | string | - |
| route | [number] | - |
UseTabsOptionsOptions to provide to the Tab Router.
Type: [Omit](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) <[DefaultNavigatorOptions](https://reactnavigation.org/docs/custom-navigators/#type-checking-navigators) <ParamListBase, any, [TabNavigationState](https://reactnavigation.org/docs/custom-navigators/#type-checking-navigators) <any>, [ExpoTabsScreenOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#expotabsscreenoptions) , [TabNavigationEventMap](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#tabnavigationeventmap) , any>, 'children'> extended by:
| Property | Type | Description |
| --- | --- | --- |
| backBehavior(optional) | TabRouterOptions[backBehavior] | - |
UseTabsWithChildrenOptionsType: PropsWithChildren<[UseTabsOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#usetabsoptions) >
UseTabsWithTriggersOptionsType: [UseTabsOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#usetabsoptions) extended by:
| Property | Type | Description |
| --- | --- | --- |
| triggers | [ScreenTrigger[]](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#screentrigger) | - |
UseTabTriggerResult| Property | Type | Description |
| --- | --- | --- |
| getTrigger | (name: string) => [Trigger](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#trigger) \| undefined | - |
| switchTab | (name: string, options: [SwitchToOptions](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#switchtooptions) ) => void | - |
| trigger(optional) | [Trigger](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#trigger) | - |
| triggerProps | [TriggerProps](https://docs.expo.dev/versions/v54.0.0/sdk/router-ui#triggerprops) | - |