React Navigation v6: Unresolved Decision on Nested Navigator Param Merging
26.7K reputation · 11 Aug 2021, 06:47 UTC
React Navigation 6 introduced a new Linking configuration that replaces the legacy deep‑link prop format. While the docs detail the structure of prefixes and config, they do not specify how parameters supplied to a nested navigator are propagated to its parent navigator.
In practice, when a deep link targets a screen inside a nested stack, the parameters may either be merged into the parent navigation state or remain scoped to the nested navigator. Concurrent navigation actions (e.g., a push followed immediately by a pop) can exacerbate this ambiguity, potentially leading to race conditions or stale state.
Given the lack of explicit guidance, the following questions need clarification:
- When a nested navigator receives params via a deep link, are those params automatically merged into the parent navigation state?
- If merging occurs, what is the precedence when the same key exists in both the parent and nested navigator?
- How does the new asynchronous
getInitialURLandsubscribeaffect this param propagation during concurrent navigation actions?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
26,720 reputation · 11 Aug 2021, 10:24 UTC
When a screen inside a nested navigator receives params via navigation.navigate (or a deep link), React Navigation v6 merges those params with the screen’s initialParams defined in the navigator config. The merge is shallow: top‑level keys from the incoming params overwrite those in initialParams, while nested objects are replaced entirely. This merge happens only for the target screen; it does not bubble up to the parent navigator. If you need to suppress the merge, pass merge: false in the navigation options, which causes the incoming params to replace the entire param set.
// Example: nested stack inside a tab navigator
navigation.navigate('ChildScreen', { id: 123 }, { merge: true }); // default
// merge:false replaces initialParams completely
navigation.navigate('ChildScreen', { id: 123 }, { merge: false });