Skip to content

Commit 740fbcf

Browse files
committed
Update root navigator initialization
1 parent 4710600 commit 740fbcf

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

versioned_docs/version-5.x/navigating-without-navigation-prop.md

+15-10
Original file line numberDiff line numberDiff line change
@@ -70,30 +70,35 @@ When writing tests, you may mock the navigation functions, and make assertions o
7070
7171
When using this pattern, you need to keep few things in mind to avoid crashes in your app.
7272
73-
- The ref is set only after the navigation container renders
73+
- The ref is set only after the navigation container renders, this can be async when handling deep links
7474
- A navigator needs to be rendered to be able to handle actions
7575
7676
If you try to navigate without rendering a navigator or before the navigator finishes mounting, it will throw and crash your app if not handled. So you'll need to add an additional check to decide what to do until your app mounts.
7777
78-
For an example, consider the following scenario, you have a screen somewhere in the app, and that screen dispatches a redux action on `useEffect`/`componentDidMount`. You are listening for this action in your middleware and try to perform navigation when you get it. This will throw an error, because by this time, the parent navigator hasn't finished mounting. Parent's `useEffect`/`componentDidMount` is always called **after** child's `useEffect`/`componentDidMount`.
78+
For an example, consider the following scenario, you have a screen somewhere in the app, and that screen dispatches a redux action on `useEffect`/`componentDidMount`. You are listening for this action in your middleware and try to perform navigation when you get it. This will throw an error, because by this time, the parent navigator hasn't finished mounting and isn't ready. Parent's `useEffect`/`componentDidMount` is always called **after** child's `useEffect`/`componentDidMount`.
7979
80-
To avoid this, you can set a ref to tell you that your app has finished mounting, and check that ref before performing any navigation. To do this, we can use `useEffect` in our root component:
80+
To avoid this, you can set a ref to tell you that your app has finished mounting, and check that ref before performing any navigation. To do this, we can use the `onReady` callback in our `NavigationContainer`:
8181
8282
```js
8383
// App.js
8484

8585
import { NavigationContainer } from '@react-navigation/native';
86-
import { navigationRef, isMountedRef } from './RootNavigation';
86+
import { navigationRef, isReadyRef } from './RootNavigation';
8787

8888
export default function App() {
8989
React.useEffect(() => {
90-
isMountedRef.current = true;
91-
92-
return () => (isMountedRef.current = false);
90+
return () => (isReadyRef.current = false);
9391
}, []);
9492

9593
return (
96-
<NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
94+
<NavigationContainer
95+
ref={navigationRef}
96+
onReady={() => {
97+
isReadyRef.current = true;
98+
}}
99+
>
100+
{/* ... */}
101+
</NavigationContainer>
97102
);
98103
}
99104
```
@@ -105,12 +110,12 @@ Also export this ref from our `RootNavigation`:
105110

106111
import * as React from 'react';
107112

108-
export const isMountedRef = React.createRef();
113+
export const isReadyRef = React.createRef();
109114

110115
export const navigationRef = React.createRef();
111116

112117
export function navigate(name, params) {
113-
if (isMountedRef.current && navigationRef.current) {
118+
if (isReadyRef.current && navigationRef.current) {
114119
// Perform navigation if the app has mounted
115120
navigationRef.current.navigate(name, params);
116121
} else {

0 commit comments

Comments
 (0)