With React Navigation 7, how must linking config be shaped so a product URL opens Product in a tabbed Shop stack with Catalog behind it?
answer
- config mirrors the navigator tree
- screens inside screens
- initialRouteName fills in the back target
- paths join the parent's path
- exact: true breaks the join
basics
~10 sReact Navigation 7's config.screens must nest exactly like the navigators: tabs, then the Shop stack, then Product. Setting initialRouteName: 'Catalog' on the Shop entry makes a linked Product open with Catalog beneath it.
solid answer
~40 sThe screens map is a tree that has to mirror the navigator tree. If `Product` lives in a `Shop` stack that is a tab inside `HomeTabs`, the config is `HomeTabs: { screens: { Shop: { screens: { Product: 'product/:sku' } } } }`. A flat `Product: 'product/:sku'` at the root produces a state that names `Product` at the root, where no such screen exists, so the link does not land. A matched link to a nested screen builds only the routes on its path, so the Shop stack would hold just `Product` and back would leave the stack; `initialRouteName: 'Catalog'` on the `Shop` entry inserts `Catalog` beneath `Product` when the path matches there. Paths also compose: a child's path is appended to its parent's path unless the child sets `exact: true`.
code
typescript · 25 linesimport type { LinkingOptions, NavigatorScreenParams } from '@react-navigation/native';
type ShopStackParamList = { Catalog: undefined; Product: { sku: string } };
type HomeTabParamList = { Shop: NavigatorScreenParams<ShopStackParamList>; Cart: undefined };
type RootStackParamList = { HomeTabs: NavigatorScreenParams<HomeTabParamList> };
export const linking: LinkingOptions<RootStackParamList> = {
prefixes: ['furnistore://', 'https://shop.example.com'],
config: {
screens: {
HomeTabs: {
screens: {
Shop: {
initialRouteName: 'Catalog',
screens: {
Catalog: 'catalog',
Product: { path: 'product/:sku', alias: ['p/:sku'] },
},
},
Cart: 'cart',
},
},
},
},
};go deeper
Remember that the screens map nests: a screen that holds a navigator gets its own screens object containing that navigator's screens.
Explain why a flat entry fails, how initialRouteName supplies the back target for a linked nested screen, and how parent paths compose.
Design paths that survive refactors of the navigator tree using exact and alias, and keep parse and stringify symmetric so shared URLs round-trip.
Decide how tightly public URLs may couple to the internal navigator tree, and what migration path exists when the tree changes.
## The shape of the app A furniture store app typically has a root stack containing a bottom-tab navigator, and each tab may hold its own stack: - `Root` stack → `HomeTabs` (tabs) and modal screens such as `NotFound` - `HomeTabs` → `Shop` (a stack), `Cart`, `Account` - `Shop` stack → `Catalog`, `Product` A shared product URL, `https://shop.example.com/product/oak-sofa`, should open `Product` in the `Shop` tab with `Catalog` underneath, so back behaves as if the customer had browsed there. ## Rule 1: the config mirrors the navigators In **React Navigation 7**, `config.screens` is a tree: an entry for a screen that renders a navigator can have its own `screens` map. `getStateFromPath` walks that tree to produce **nested state** — a route for `HomeTabs` whose state has a route for `Shop` whose state has a route for `Product`. ```tsx config: { screens: { HomeTabs: { screens: { Shop: { initialRouteName: 'Catalog', screens: { Catalog: 'catalog', Product: 'product/:sku', }, }, Cart: 'cart', }, }, }, } ``` The common mistake is a **flat config** — `Product: 'product/:sku'` directly under the root `screens`. The path still matches, but the state it produces names `Product` as a root route. The root stack has no screen called `Product`, so the state cannot be used and the link does not open the product. ## Rule 2: the back target is not implied A link builds only the routes on its path. Without further configuration, the `Shop` stack's state would contain just `Product`; back from it would leave the stack rather than show the catalog. | Config on the `Shop` entry | `Shop` stack after the link | Back from `Product` | |---|---|---| | none | `Product` | leaves the Shop stack | | `initialRouteName: 'Catalog'` | `Catalog`, `Product` | shows `Catalog` | `initialRouteName` in a path config applies **when the path matches inside that navigator**: React Navigation inserts that route before the matched one. The root `config` object accepts an `initialRouteName` as well, for the root navigator. ## Rule 3: paths compose A nested screen's path is, by default, **relative to its parent's path**. If `Shop` had `path: 'shop'`, then `Product: 'product/:sku'` would match `shop/product/oak-sofa`. Two tools adjust that: - `exact: true` on a child makes its path absolute, ignoring the parents' paths — useful to keep `product/:sku` short while `Shop` has a path of its own. - `alias` lists additional paths that match the same screen, for example an old `p/:sku` URL that marketing already printed. A parent without a `path` — like `HomeTabs` above — contributes nothing, which is why it is common to give paths only to leaf screens. ## Parsing and building Per-screen options sit next to `path`: `parse` converts incoming params (`parse: { qty: Number }`), `stringify` converts outgoing ones when a state is turned back into a path with `getPathFromState`. The same config is used in both directions, so building a share URL for the current product produces the same `product/oak-sofa` a customer can paste back. ## Validation help React Navigation validates the config's shape when the container renders it. An unknown key at the wrong level — say `parse` on the root `config`, or a typo such as `screen` for `screens` — throws an error listing the invalid properties and the ones allowed there. A structurally valid config can still be *semantically* wrong (flat instead of nested), which shows up as links that do nothing. ## What a strong answer shows It draws the navigator tree, writes a config that mirrors it, explains why the flat version fails, adds `initialRouteName` for a sensible back stack, and mentions how parent paths compose with `exact` and `alias` as escape hatches.
- Why does TypeScript accept a nested screens map under HomeTabs but not under Cart?The `PathConfigMap` type only allows `screens` and `initialRouteName` for a route whose param type is `NavigatorScreenParams<…>`, meaning it renders a nested navigator. `Cart` is a plain screen, so its entry may only be a path string or a path object with options such as `parse`.
- Marketing printed short URLs like /p/oak-sofa; how do you support them without a second screen?Add `alias: ['p/:sku']` to the `Product` path config. An alias is an extra pattern that matches the same screen, so both `product/oak-sofa` and `p/oak-sofa` open `Product` with `sku` set, while building a path from state still produces the main `product/:sku` form.
saying these in an interview costs you the question
- A flat Product: 'product/:sku' at the root works for nested screens too.
- A linked Product automatically gets Catalog beneath it because Catalog is the stack's first screen.
- A child screen's path always ignores its parent's path.
- React Navigation infers the nesting from the navigators, so the config shape does not matter.