In React Navigation 7, what happens when a URL matches no linking path, and how do you route it to a NotFound screen?
answer
- no match means no state
- launch falls back to the initial screen
- '*' is the catch-all pattern
- wildcard loses to specific paths
- filter skips URLs on purpose
basics
~20 sAn unmatched URL yields no state in React Navigation 7, so a cold start opens the default initial screen and a running app ignores the link. A screen with the path '*' catches every path that nothing more specific matches.
solid answer
~40 s`getStateFromPath` returns `undefined` when no pattern matches. At launch the container then has no linked state and opens on its normal initial screen; for a URL arriving while the app runs, the listener has no state and does nothing. Either way the customer tapped a link and nothing explains why they are on the home screen. Adding a screen such as `NotFound: '*'` fixes that: `*` matches any path, and React Navigation ranks wildcard segments below static and param segments, so `product/:sku` still wins and only truly unknown paths fall through. Two related tools: `filter` lets you skip URLs on purpose, such as an auth redirect, and `alias` or a wrapping `getStateFromPath` can map old URLs onto current screens instead of sending them to `NotFound`.
code
typescript · 27 linesimport { getStateFromPath, type LinkingOptions } from '@react-navigation/native';
import type { RootStackParamList } from './types';
export const linking: LinkingOptions<RootStackParamList> = {
prefixes: ['furnistore://', 'https://shop.example.com'],
filter: (url) => !url.includes('/oauth/callback'),
config: {
screens: {
HomeTabs: {
screens: {
Shop: {
initialRouteName: 'Catalog',
screens: {
Catalog: 'catalog',
Product: 'product/:sku',
},
},
},
},
NotFound: '*',
},
},
getStateFromPath(path, options) {
const rewritten = path.replace(/^\/?item\//, 'product/');
return getStateFromPath(rewritten, options);
},
};go deeper
Know that an unknown path does not navigate anywhere by itself, and that a screen with the path '*' catches unmatched links.
Explain cold versus warm behaviour for unmatched URLs, the ranking that keeps specific paths ahead of the wildcard, and what filter does.
Plan for legacy URLs with alias or a wrapped getStateFromPath, validate matched params on the target screen, and tell config bugs apart from undelivered links.
Own the long-lived URL contract: which shared links must keep working across releases and how removed content degrades for customers.
## What "no match" means In **React Navigation 7**, an incoming URL goes through `getStateFromPath` after its prefix is stripped. When no pattern in `config.screens` matches, that function returns **`undefined`**, and the behaviour depends on when the URL arrived: 1. **At launch (cold start).** The container asked `getInitialURL` for the launch URL, got a URL, but could not turn it into state. It renders with no linked state, so the root navigator starts on its usual initial screen. 2. **While the app runs (warm).** The URL listener computes no state and simply returns. No navigation happens. It also returns nothing when the URL has **no matching prefix** — a link on a domain or scheme you forgot to list in `prefixes`. And a `getStateFromPath` that throws is caught and logged with `console.error`, again producing no state. In a furniture store that means a customer taps a shared link for a discontinued product category, the app opens on the home tab, and nothing tells them why. That silent fallback is the thing to fix. ## Catching unknown paths with a wildcard A path pattern of **`*`** matches any path. The usual setup is a `NotFound` screen at the root: ```tsx config: { screens: { HomeTabs: { screens: { /* ... */ } }, NotFound: '*', }, } ``` React Navigation sorts candidate patterns so that **static segments beat param segments, and both beat wildcards**. `product/:sku` therefore still matches `product/oak-sofa`; only a path that nothing else matches ends up at `NotFound`. The wildcard also catches unmatched paths that would otherwise have been nested — the whole path is matched against the configs, not segment by segment in isolation. | Incoming path | Matches | Result | |---|---|---| | `product/oak-sofa` | `product/:sku` | `Product` with `sku: 'oak-sofa'` | | `catalog` | `catalog` | `Catalog` | | `sale/2019-spring` | only `*` | `NotFound` | | (no matching prefix) | — | not handled at all | The `NotFound` screen can read its own route path to show what was requested and offer a way back to the catalog. ## Unknown is not always "not found" Some URLs are known but should not become screens, and some are old but still meaningful: - **`filter`** — a function on the linking options that receives the URL and returns whether React Navigation should handle it. Returning `false` for an authentication redirect URL, for example, keeps it from being matched (and from landing on `NotFound`). - **`alias`** — extra patterns on a screen's path config, such as `p/:sku` for old short links, so they open the real screen. - **A custom `getStateFromPath`** — the linking options accept your own function. Wrapping the default one, which `@react-navigation/native` exports, lets you rewrite a legacy path before matching, or return a specific state for it. ## Where "matched" still is not "valid" A wildcard proves the path had some shape, not that it is safe. `Product` matched with `sku: '../../admin'` is still a matched link. The target screen must handle an unknown `sku` — show "this item is no longer available" rather than crash or render an empty page — and must treat the value as untrusted input. ## Debugging an unmatched link - Check the prefix: is the exact scheme and host, including `https` and any subdomain, in `prefixes`? - Call the exported `getStateFromPath` with the path and your config in a unit test and inspect the result. - Remember that a link the OS never delivered looks identical from the app's point of view: nothing happens. If `getInitialURL` or the listener never fires, the problem is native registration, not the config. ## What a strong answer shows It states the silent behaviour for both cold and warm URLs, adds `'*'` with the ranking rule that keeps specific paths winning, and distinguishes deliberately skipped URLs (`filter`) and legacy URLs (`alias`, custom `getStateFromPath`) from truly unknown ones.
- Why does NotFound: '*' not swallow /product/oak-sofa?React Navigation ranks candidate patterns: static segments outrank param segments, which outrank wildcards. `product/:sku` is more specific than `*`, so it wins for any product path. The wildcard only matches what no other pattern accepts.
- When should a URL be filtered out rather than sent to NotFound?When it is a known URL that is not meant to become a screen — an authentication redirect, a link another part of the app consumes. `filter` returning `false` makes React Navigation ignore it entirely, so it neither navigates nor lands on NotFound.
Like a mail room's sorting frame: letters go to the most specific pigeonhole that fits, and only what fits nowhere lands in the dead-letter tray instead of vanishing.
saying these in an interview costs you the question
- An unmatched URL throws and crashes the app on launch.
- A '*' route catches everything, so it must be listed last to avoid shadowing product paths.
- React Navigation shows a built-in not-found screen for unknown paths.
- If a link does nothing, the linking config must be wrong.