Skip to main content
Glama
singular.md3.2 kB
--- title: Singular stack routes description: Learn how to enforce singular routes. --- > **warning** Singular routes are available from SDK 53 and above. They are currently flagged as `dangerouslySingular` due to an upstream issue with `react-native-screens`. Expo is working with Software Mansion to resolve the issue. While a `Stack` normally operates with `push`/`pop` actions, in advanced scenarios you may wish to enforce a singular version of a screen in the stack. When enabled, any time a new screen is pushed the history will be scanned and any matching screens will be removed to ensure only a singular version exists. ## Options There are two options for conditions: - `true`: Use the default singular function - `Function`: Specify your own singular function The default singular function returns the screen's pathname without search params or the hash. The singular identifier function has the signature of `(routeName: string, params: Record<string, string | string[]>) => string | undefined`. ## Assigning singular on the navigator Using the above example app, you can create a singular constraint to ensure that each `[profile]` page is unique. ```tsx app/_layout.tsx return ( <Stack.Screen name="[profile]" dangerouslySingular={({ profile }) => profile} /> ); } ``` If you now navigate to `/profile-2` and your history is: - `/profile-1` - `/profile-2` - `/profile-3` The new history will push the new route, but also remove any previous entries: - `/profile-1` - `/profile-3` - `/profile-2` ## Creating singular Links `dangerouslySingular` can also be added to the `` component to create links that enforce singular routes. ```tsx <Link href="/unique-link" dangerouslySingular={(name) => name === 'unique-link' ? name : undefined} /> ``` ## Using the imperative API The imperative API also accepts a `dangerouslySingular` option. ```tsx router.navigate('/unique-link', { dangerouslySingular: true }); router.navigate('/unique-link', { dangerouslySingular: name => (name === 'unique-link' ? name : undefined), }); router.push('/unique-link', { dangerouslySingular: true }); router.push('/unique-link', { dangerouslySingular: name => (name === 'unique-link' ? name : undefined), }); ``` ## Navigate vs push The `navigate` and `push` events apply the singular constraint differently. - _navigate_: Only applies the constraint if the current route is changed - _push_: Always applies the constraint Using the app structure above, if you have the history of: - `/profile-1` - `/profile-2` - `/profile-2` - `/profile-3` - `/profile-2` If you navigate to `/profile-2`, the singular constraint will not be applied as the current route is the target route when using `navigate`. However, if you push `/profile-2`, the singular constraint will be applied. ```tsx // Will NOT apply the singular constraint as the current route is the target route router.navigate("/profile-2", { dangerouslySingular: (_, { profile } => profile === 'profile-2' ? profile : undefined ) }) // Will apply the singular constraint router.push("/profile-2", { dangerouslySingular: (_, { profile } => profile === 'profile-2' ? profile : undefined ) }) ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jaksm/expo-docs-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server