1--- 2title: Navigate between pages 3description: Create links to move between pages. 4--- 5 6import { BoxLink } from '~/ui/components/BoxLink'; 7import { BookOpen02Icon } from '@expo/styleguide-icons'; 8import { FileTree } from '~/ui/components/FileTree'; 9 10Expo Router uses "links" to move between pages in the app. This is conceptually similar to how the web works with `<a>` tags and the `href` attribute. 11 12<FileTree files={['app/index.js', 'app/about.js', 'app/user/[id].js']} /> 13 14In the following example, there are two `<Link />` components which navigate to different routes. 15 16{/* prettier-ignore */} 17```js app/index.js 18import { View } from 'react-native'; 19/* @info Import the <b>Link</b> React component from <b>expo-router</b> */ 20import { Link } from 'expo-router'; 21/* @end */ 22 23export default function Page() { 24 return ( 25 <View> 26 /* @info Tapping this will link to the <b>about</b> page */ 27 <Link href="/about">About</Link> 28 /* @end */ 29 30 /* @info Tapping this will navigate to the dynamic route <b>user/[id]</b> where <b>id=bacon</b> */ 31 <Link href="/user/bacon">View user</Link> 32 /* @end */ 33 </View> 34 ); 35} 36``` 37 38## Buttons 39 40The Link component wraps the children in a `<Text>` component by default, this is useful for accessibility but not always desired. You can customize the component by passing the `asChild` prop, which will forward all props to the first child of the `Link` component. The child component must support the `onPress` and `onClick` props, `href` and `accessibilityRole` will also be passed down. 41 42{/* prettier-ignore */} 43```js 44import { Pressable, Text } from "react-native"; 45import { Link } from "expo-router"; 46 47export default function Page() { 48 return ( 49 /* @info The <b>onPress</b> event that navigates to <b>/other</b> will be passed to <b>Pressable</b> */ 50 <Link href="/other" asChild> 51 /* @end */ 52 <Pressable> 53 <Text>Home</Text> 54 </Pressable> 55 </Link> 56 ); 57} 58``` 59 60## Imperative navigation 61 62You may want to navigate from a global store when a user logs in or out. You can use the `router` object to navigate imperatively (outside of React). 63 64```js 65import { router } from 'expo-router'; 66 67export function logout() { 68 /* @info Navigate to <b>/login</b> */ 69 router.replace('/login'); 70 /* @end */ 71} 72``` 73 74The `router` object is immutable and contains the following functions: 75 76- **push**: `(href: Href) => void` Navigate to a route. You can provide a full path like **/profile/settings** or a relative path like **../settings**. Navigate to dynamic routes by passing an object like `{ pathname: 'profile', params: { id: '123' } }`. 77- **replace**: `(href: Href) => void` Same API as push but replaces the current route in the history instead of pushing a new one. This is useful for redirects. 78- **back**: `() => void` Navigate back to previous route. 79- **canGoBack**: `() => boolean` Returns `true` if a valid history stack exists and the `back()` function can pop back. 80- **setParams**: `(params: Record<string, string>) => void` Update the query params for the currently selected route. 81 82## Linking to dynamic routes 83 84Dynamic routes and query parameters can be provided statically or with the convenience **Href** object. 85 86{/* prettier-ignore */} 87```js app/index.js 88/* @info Import the <b>Link</b> React component from <b>expo-router</b> */ 89import { Link } from 'expo-router'; 90/* @end */ 91 92export default function Page() { 93 return ( 94 <View> 95 <Link 96 href={{ 97 /* @info Navigate to <b>/user/bacon</b> */ 98 pathname: "/user/[id]", 99 params: { id: 'bacon' } 100 /* @end */ 101 }}> 102 View user 103 </Link> 104 </View> 105 ); 106} 107``` 108 109## Replacing screens 110 111By default, links "push" routes onto the navigation stack. This means that the previous screen will be available when the user navigates back. You can use the `replace` prop to replace the current screen instead of pushing a new one. 112 113{/* prettier-ignore */} 114```js app/index.js 115import { Link } from 'expo-router'; 116 117export default function Page() { 118 return ( 119 <View> 120 <Link 121 /* @info Navigate to <b>/feed</b> without adding it to the stack. */ 122 replace 123 /* @end */ 124 href="/feed"> 125 Login 126 </Link> 127 </View> 128 ); 129} 130``` 131 132Use **router.replace()** to replace the current screen imperatively. 133 134Native navigation does not always support `replace`. For example on Twitter, you wouldn't be able to "replace" directly from a profile to a tweet, this is because the UI requires a back button to return to the feed or other top-level tab screen. In this case, replace would switch to the feed tab, and push the tweet route on top of it, or if you were on a different tweet inside the feed tab, it would replace the current tweet with the new tweet. This exact behavior can be obtained in Expo Router by using [`unstable_settings`](/router/advanced/router-settings). 135 136## Autocomplete 137 138Expo Router can automatically generate static TypeScript types for all routes in your app. This allows you to use autocomplete for `href`s and get warnings when invalid links are used. Learn more: [Statically Typed Routes](/router/reference/typed-routes). 139 140## Web behavior 141 142Expo Router supports the standard `<a>` element when running on web, however this will perform a full-page server-navigation. This is slower and doesn't take full advantage of React. Instead, the Expo Router `<Link>` component will perform client-side navigation, this will preserve the state of the website and navigate faster. 143 144Client-side navigation works with both single-page apps, and [static rendering](/router/reference/static-rendering). 145 146## Usage in simulators 147 148See the [testing URLs](/guides/linking#testing-urls) guide to learn how you can emulate deep links in simulators and emulators. 149 150## Next steps 151 152<BoxLink 153 title="Layouts and UI" 154 Icon={BookOpen02Icon} 155 description="Learn how to create shared UI elements like headers and tab bars." 156 href="/routing/layouts/" 157/> 158