With React Navigation 7, what do the linking prop's prefixes and config.screens do when a shared furniture-store product URL opens the app?
answer
- prefix stripped, path left over
- screen name maps to a path pattern
- :sku becomes a string param
- query string lands in params too
- OS registration is a separate job
basics
~20 sIn React Navigation 7, linking.prefixes are stripped from the incoming URL, and the remaining path is matched against config.screens, which maps screen names to path patterns; matched segments and query values become that screen's params.
solid answer
~40 sWhen `NavigationContainer` gets a `linking` prop, React Navigation handles incoming URLs for it. `prefixes` lists the scheme and host parts to strip — say `furnistore://` and `https://shop.example.com` — so `https://shop.example.com/product/oak-sofa?color=walnut` becomes the path `product/oak-sofa?color=walnut`. That path is matched against `config.screens`, an object from screen name to path pattern: with `Product: 'product/:sku'` the navigator opens `Product` with params `{ sku: 'oak-sofa', color: 'walnut' }` — path segments and query values both arrive, as strings unless you add `parse`. By default the container reads the launch URL with `Linking.getInitialURL()` and later URLs with a `'url'` listener. What `linking` does not do is register the scheme or domain with iOS and Android; that is native configuration, and a URL the OS never delivers never reaches this code.
code
tsx · 24 linesimport * as React from 'react';
import { NavigationContainer, type LinkingOptions } from '@react-navigation/native';
import { RootStack, type RootStackParamList } from './RootStack';
const linking: LinkingOptions<RootStackParamList> = {
prefixes: ['furnistore://', 'https://shop.example.com'],
config: {
screens: {
Catalog: 'catalog',
Product: {
path: 'product/:sku',
parse: { qty: Number },
},
},
},
};
export function App() {
return (
<NavigationContainer linking={linking}>
<RootStack />
</NavigationContainer>
);
}go deeper
Recall the two fields: prefixes are stripped from the URL, and config.screens maps each screen name to a path pattern whose :params become route params.
Explain the flow from getInitialURL or subscribe through getStateFromPath to initial state or a dispatched action, and why params are strings unless parsed.
Separate React Navigation's URL-to-state job from native link registration, and treat params from a shared URL as untrusted input on the target screen.
Treat the URL scheme as a public contract: plan which paths are stable, how old links keep working, and who owns changes to the map.
## What the linking prop is for A furniture store shares product pages as URLs — in chats, emails and ads. When one of those URLs opens the app, **React Navigation 7** has to turn it into navigation state: which screen, with which params. The `linking` prop on `NavigationContainer` holds that mapping. Providing it turns deep-link handling on (unless `linking.enabled` is `false`). The two parts every config has: - **`prefixes`** — the beginnings of URLs the app accepts, typically the custom scheme plus the web domain: `['furnistore://', 'https://shop.example.com']`. A prefix with a wildcard subdomain such as `'https://*.example.com'` is also accepted. Prefixes are stripped before matching, so both `furnistore://product/oak-sofa` and `https://shop.example.com/product/oak-sofa` leave the same path. - **`config.screens`** — an object whose keys are **screen names** and whose values are **path patterns** (or objects with a `path` and more options). ## How a URL becomes a screen 1. The container obtains the URL — at launch through `getInitialURL` (by default React Native's `Linking.getInitialURL()`), later through `subscribe` (by default a `Linking.addEventListener('url', …)` listener). 2. It strips the first matching prefix. If no prefix matches, the URL is not handled. 3. It runs `getStateFromPath` on the remaining path against `config.screens`. 4. At launch the result becomes the container's initial state; for a URL arriving while the app runs, the state is converted to a navigation action and dispatched. ## Params: what the screen receives | URL part | Pattern | Param on the screen | |---|---|---| | `/product/oak-sofa` | `Product: 'product/:sku'` | `sku: 'oak-sofa'` | | `?color=walnut` | (any query string) | `color: 'walnut'` | | `?qty=2` | with `parse: { qty: Number }` | `qty: 2` | Two details interviewers check: - **Everything is a string by default.** A path segment or a query value is text; a screen that expects a number must declare a `parse` function for that param, or convert it itself. - **Query parameters are merged into the focused screen's params**, alongside the path params. The inverse mapping exists too: `getPathFromState` turns a navigation state back into a path using the same config, which is how React Navigation builds web URLs and how helpers such as `useRoutePath` compute the path for the current screen — handy for a "Share this sofa" button. ## Static configuration With the static API, each screen can carry its own `linking` value (for example `linking: 'product/:sku'`), and the component created by `createStaticNavigation` accepts a `linking` prop with the `prefixes`. Setting `enabled: 'auto'` there generates a kebab-case path for every leaf screen that has none. The matching rules are the same as with the dynamic API. ## What linking does not do - It does **not** register the custom scheme or the verified web domain with the operating system. That is native configuration (URL types on iOS, intent filters on Android, plus the domain verification files), and if the OS does not deliver the URL to the app, React Navigation never sees it. - It does **not** validate params. `sku` is untrusted input from outside the app; the product screen must treat an unknown or malformed value as a normal case. - It does **not** decide what happens to unmatched paths beyond "no match" — a catch-all route is something you add. ## Common misreadings - Treating `prefixes` as a security allow-list for the whole app: they only decide which URLs React Navigation parses, not which apps may send them. - Expecting the same config to work unchanged after moving a screen into a nested navigator: the screens map has to be nested to match. - Assuming a link opens a fresh copy of the app: on a warm start, the URL becomes an action dispatched into the running navigation tree. ## A good interview answer Name both fields and what they do (strip, then match), show one pattern with a path param, say that params are strings and that query values arrive too, and draw the line between React Navigation's job — URL to state — and the platform's job — delivering the URL to the app at all.
- Why might the Product screen get the string '2' when it expects the number 2?Path segments and query values are parsed from text, so every param arrives as a string by default. Declaring `parse: { qty: Number }` on the screen's path config converts that param during parsing; without it, the screen has to convert and validate the value itself.
- The linking config is correct, but tapping the link in a chat opens the browser instead of the app. Is that a React Navigation problem?Usually not. React Navigation only handles URLs the operating system delivers to the app. If the scheme or verified domain is not registered natively, or domain verification failed, the OS opens the browser and the linking config never runs. That diagnosis belongs to the platform's deep-link setup.
saying these in an interview costs you the question
- Adding prefixes to the linking prop registers the URL scheme with iOS and Android.
- Path params arrive as numbers when the URL segment looks numeric.
- Query string values are dropped; only path segments become params.
- config.screens is keyed by URL path rather than by screen name.
- A deep link needs a manual Linking listener in every screen that can be opened.