Skip to content

Commit abe167e

Browse files
committed
Document behavior of inactive screens
1 parent 414e3f2 commit abe167e

File tree

7 files changed

+58
-27
lines changed

7 files changed

+58
-27
lines changed

versioned_docs/version-8.x/bottom-tab-navigator.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,13 +321,9 @@ It supports the following values:
321321

322322
Defaults to `pause`.
323323

324-
If you set [`lazy: false`](#lazy) or [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused. This makes sure that effects are run to initialize the screen.
324+
If you set [`lazy: false`](#lazy) or [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused.
325325

326-
:::info
327-
328-
React Navigation determines whether a screen is inactive based on various factors such as gestures, animations, and other interactions after it becomes unfocused.
329-
330-
:::
326+
See [Inactive screens](navigation-lifecycle.md#inactive-screens) for more details.
331327

332328
#### `lazy`
333329

versioned_docs/version-8.x/drawer-navigator.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,9 @@ It supports the following values:
274274

275275
Defaults to `pause`.
276276

277-
If you set [`lazy: false`](#lazy) or [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused. This makes sure that effects are run to initialize the screen.
277+
If you set [`lazy: false`](#lazy) or [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused.
278+
279+
See [Inactive screens](navigation-lifecycle.md#inactive-screens) for more details.
278280

279281
#### `lazy`
280282

versioned_docs/version-8.x/material-top-tab-navigator.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,9 @@ It supports the following values:
365365

366366
Defaults to `pause`.
367367

368-
If you set [`lazy: false`](#lazy) or [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused. This makes sure that effects are run to initialize the screen.
368+
If you set [`lazy: false`](#lazy) or [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused.
369369

370-
:::info
371-
372-
React Navigation determines whether a screen is inactive based on various factors such as gestures, animations, and other interactions after it becomes unfocused.
373-
374-
:::
370+
See [Inactive screens](navigation-lifecycle.md#inactive-screens) for more details.
375371

376372
#### `title`
377373

versioned_docs/version-8.x/native-stack-navigator.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,9 @@ It supports the following values:
106106

107107
Defaults to `pause`.
108108

109-
If you [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused. This makes sure that effects are run to initialize the screen.
109+
If you [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused.
110110

111-
:::info
112-
113-
React Navigation determines whether a screen is inactive based on various factors such as gestures, animations, and other interactions after it becomes unfocused.
114-
115-
:::
111+
See [Inactive screens](navigation-lifecycle.md#inactive-screens) for more details.
116112

117113
#### `title`
118114

versioned_docs/version-8.x/navigation-lifecycle.md

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export default function App() {
165165

166166
We start on the `HomeScreen` and navigate to `DetailsScreen`. Then we use the tab bar to switch to the `SettingsScreen` and navigate to `ProfileScreen`. After this sequence of operations is done, all 4 of the screens are mounted! If you use the tab bar to switch back to the `HomeStack`, you'll notice you'll be presented with the `DetailsScreen` - the navigation state of the `HomeStack` has been preserved!
167167

168-
## React Navigation lifecycle events
168+
## Lifecycle events
169169

170170
Now that we understand how React lifecycle methods work in React Navigation, let's answer an important question: "How do we find out that a user is leaving (blur) it or coming back to it (focus)?"
171171

@@ -331,9 +331,54 @@ To render different things based on whether the screen is focused, we can use th
331331

332332
To know the focus state inside of an event listener, we can use the [`navigation.isFocused()`](navigation-object.md#isfocused) method. Note that using this method doesn't trigger a re-render like the `useIsFocused` hook does, so it is not suitable for rendering different things based on focus state.
333333

334+
## Inactive screens
335+
336+
Many navigators also have an `inactiveBehavior` option that lets you "pause" screens when they are inactive:
337+
338+
```js static2dynamic
339+
const MyTabs = createBottomTabNavigator({
340+
screenOptions: {
341+
// highlight-next-line
342+
inactiveBehavior: 'pause',
343+
},
344+
screens: {
345+
Home: createBottomTabScreen({
346+
screen: HomeScreen,
347+
}),
348+
Profile: createBottomTabScreen({
349+
screen: ProfileScreen,
350+
}),
351+
},
352+
});
353+
```
354+
355+
Here, "inactive" and "unfocused" have different meanings:
356+
357+
- A screen becomes "unfocused" as soon as you navigate away from it
358+
- A screen becomes "inactive" based on various factors, such as gestures, animations, and other interactions after it becomes unfocused - without guarantees on timing
359+
- [Preloaded](navigation-actions.md#preload) screens don't become inactive until after the first time they become focused, so their effects can run to initialize the screen
360+
- Focus and blur are part of navigation lifecycle, but "inactive" is an optimization mechanism
361+
362+
When a screen is paused, the following things happen:
363+
364+
- Effects are cleaned up (similar to when a component unmounts)
365+
- Content stays rendered and the state is preserved
366+
- Content can still re-render at a lower priority
367+
368+
This means event listeners, subscriptions, timers etc. get cleaned up. This reduces unnecessary re-renders and resource usage for paused screens.
369+
370+
Side effects from events can still run. For example, if you have a audio player that emits progress updates, audio will keep playing and progress updates will keep coming in even when the screen is paused. To avoid this, you need to use [lifecycle events](#lifecycle-events) to pause the audio when the screen becomes unfocused.
371+
372+
:::info
373+
374+
Pausing screens is not a replacement for lifecycle events. Treat it as an optimization mechanism only. If you need guarantees on when things get cleaned up, use lifecycle events such as [`blur`](navigation-events.md#blur) or [`useFocusEffect`](use-focus-effect.md).
375+
376+
:::
377+
334378
## Summary
335379

336380
- Screens stay mounted when navigating away from them
337381
- The [`useFocusEffect`](use-focus-effect.md) hook is like [`useEffect`](https://react.dev/reference/react/useEffect) but tied to the navigation lifecycle instead of the component lifecycle
338382
- The [`useIsFocused`](use-is-focused.md) hook and [`navigation.isFocused()`](navigation-object.md#isfocused) method can be used to determine if a screen is currently focused
339383
- The [`focus`](navigation-events.md#focus) and [`blur`](navigation-events.md#blur) events can be used to know when a screen gains or loses focus
384+
- The `inactiveBehavior` option can be used to "pause" screens when they are inactive, which cleans up effects but keeps the content rendered and state preserved

versioned_docs/version-8.x/stack-navigator.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,9 @@ It supports the following values:
125125

126126
Defaults to `pause`.
127127

128-
If you [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused. This makes sure that effects are run to initialize the screen.
128+
If you [`preload`](navigation-actions.md#preload) a screen, it won't be paused until after the first time it becomes focused.
129129

130-
:::info
131-
132-
React Navigation determines whether a screen is inactive based on various factors such as gestures, animations, and other interactions after it becomes unfocused.
133-
134-
:::
130+
See [Inactive screens](navigation-lifecycle.md#inactive-screens) for more details.
135131

136132
#### `title`
137133

versioned_docs/version-8.x/upgrading-from-7.x.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ createStackNavigator({
507507
</TabItem>
508508
</Tabs>
509509

510-
See [Stack Navigator](stack-navigator.md#inactivebehavior), [Native Stack Navigator](native-stack-navigator.md#inactivebehavior), [Bottom Tab Navigator](bottom-tab-navigator.md#inactivebehavior), [Drawer Navigator](drawer-navigator.md#inactivebehavior), and [Material Top Tab Navigator](material-top-tab-navigator.md#inactivebehavior) for more details.
510+
See [Inactive screens](navigation-lifecycle.md#inactive-screens) for more details.
511511

512512
#### The `onChangeText` callback has been renamed to `onChange` for `headerSearchBarOptions`
513513

0 commit comments

Comments
 (0)