Skip to content

Commit 83c1456

Browse files
committed
Update upgrade guide
1 parent 8def11a commit 83c1456

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

versioned_docs/version-8.x/configuring-links.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,44 @@ In the above example, the following path formats are handled:
260260
- `/user` navigates to the `Profile` screen
261261
- `/feed/:sort` navigates to the `Chat` screen with the param `sort`
262262

263+
In addition, if you are using [`groups`](group.md) in your navigator, you can specify the `linking` property for the group to apply it to all screens in the group. The path specified in the group will be used as a prefix for all screens in the group. For example:
264+
265+
```js
266+
const RootStack = createStackNavigator({
267+
screens: {
268+
Home: {
269+
screen: HomeScreen,
270+
linking: 'home',
271+
},
272+
},
273+
groups: {
274+
// highlight-start
275+
Admin: {
276+
linking: 'admin',
277+
screens: {
278+
Dashboard: {
279+
screen: DashboardScreen,
280+
linking: 'dashboard',
281+
},
282+
Settings: {
283+
screen: SettingsScreen,
284+
linking: 'settings',
285+
},
286+
},
287+
},
288+
// highlight-end
289+
},
290+
});
291+
```
292+
293+
This results in:
294+
295+
- `/home` navigates to the `Home` screen
296+
- `/admin/dashboard` navigates to the `Dashboard` screen
297+
- `/admin/settings` navigates to the `Settings` screen
298+
299+
Any other options specified for the group such as [`parse` and `stringify`](#passing-params) are shallow merged with the options specified for the screens. If the same option is specified in both the group and the screen, the one specified in the screen will take precedence.
300+
263301
### How does automatic path generation work?
264302

265303
When using automatic path generation with `enabled: 'auto'`, the following rules are applied:

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ To work with the reworked TypeScript types, custom navigators now need to provid
238238
+ }
239239
```
240240

241+
It's a bit verbose, but we don't have a better way due to limitations of TypeScript.
242+
241243
See [Custom navigators](custom-navigators.md) for more details.
242244

243245
### Changes to navigators
@@ -456,6 +458,57 @@ import { useFrameSize } from '@react-navigation/elements';
456458
const isLandscape = useFrameSize((size) => size.width > size.height);
457459
```
458460

461+
#### `detachInactiveScreens` and `freezeOnBlur` have been replaced with `inactiveBehavior`
462+
463+
Previously, Stack, Native Stack, Bottom Tab, and Drawer Navigators accepted a `detachInactiveScreens` prop - used to detach inactive screens from the native view hierarchy to save memory via [`react-native-screens`](https://github.com/software-mansion/react-native-screens). Additionally, Stack Navigator accepted a `detachPreviousScreen` option to detach the previous screen when navigating to a new screen.
464+
465+
They also had an experimental `freezeOnBlur` option to freeze the screen when it's not focused - which would prevent it from re-rendering and running effects.
466+
467+
These were a source of significant maintenance burden. So we're working on alternative and more integrated approaches.
468+
469+
Now they have been replaced with a new `inactiveBehavior` screen option available in all navigators. It supports the following values:
470+
471+
- `pause`: Effects are cleaned up - e.g. timers are cleared, subscriptions are removed, etc. This avoids unnecessary renders when the screen is inactive.
472+
- `none`: Screen renders normally.
473+
474+
It defaults to `pause`.
475+
476+
This is not a direct replacement as the behavior differs. For example, `freezeOnBlur` prevents screens from re-rendering entirely but keeps the effects running, while `inactiveBehavior: 'pause'` cleans up effects avoiding re-renders due to timers, subscriptions, etc., but the screen can still re-render at a lower priority due to changes in props, context etc.
477+
478+
To update your code, remove `detachInactiveScreens`, `detachPreviousScreen`, and `freezeOnBlur` usage:
479+
480+
<Tabs groupId="config" queryString="config">
481+
<TabItem value="static" label="Static" default>
482+
483+
```diff lang=js
484+
createStackNavigator({
485+
- detachInactiveScreens: true,
486+
screenOptions: {
487+
- detachPreviousScreen: true,
488+
- freezeOnBlur: true,
489+
},
490+
// ...
491+
});
492+
```
493+
494+
</TabItem>
495+
<TabItem value="dynamic" label="Dynamic">
496+
497+
```diff lang=js
498+
<Stack.Navigator
499+
- detachInactiveScreens={true}
500+
screenOptions={{
501+
- detachPreviousScreen: true,
502+
- freezeOnBlur: true,
503+
}}
504+
>
505+
```
506+
507+
</TabItem>
508+
</Tabs>
509+
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.
511+
459512
#### The `onChangeText` callback has been renamed to `onChange` for `headerSearchBarOptions`
460513

461514
The `onChangeText` option in `headerSearchBarOptions` was confusingly named after text input's
@@ -797,6 +850,35 @@ const MyTheme = {
797850

798851
See [Themes](themes.md#using-platform-colors) for more details.
799852

853+
### Linking config now supports Standard Schema
854+
855+
The `parse` property in the linking config now accepts schemas from [Standard Schema](https://standardschema.dev/) compatible libraries such as [Zod](https://zod.dev/), [Valibot](https://valibot.dev/) or [ArkType](https://arktype.io/) in addition to parse functions:
856+
857+
```js
858+
import { z } from 'zod';
859+
860+
const RootStack = createStackNavigator({
861+
screens: {
862+
Profile: {
863+
screen: ProfileScreen,
864+
linking: {
865+
path: 'user/:id',
866+
parse: {
867+
id: z.coerce.number(),
868+
},
869+
},
870+
},
871+
},
872+
});
873+
```
874+
875+
Compared to parse functions, schemas provide a few advantages:
876+
877+
- **Support for validation and fallback**: A parse function only parses the param. A schema can also validate the param. If the validation fails, the URL won't match the current screen and React Navigation will try the next matching config. Schemas are also called with `undefined` when a query param is missing, which lets them provide a fallback, while parse functions are not called when a query param is missing.
878+
- **Better Query Param handling with TypeScript**: When using [Static Configuration](static-configuration.md), query params (e.g. `?foo=bar`) are always inferred as optional with `parse` functions. With schemas, you can specify whether a query param is required (e.g. `z.string()`) or optional (e.g. `z.string().optional()`).
879+
880+
See [Configuring links](configuring-links.md#using-standard-schema) and [TypeScript](typescript.md#parse-function-vs-standard-schema) for more details.
881+
800882
### Groups now support `linking` option in static configuration
801883

802884
The `linking` option can now be specified for groups in static configuration to define nested paths:

0 commit comments

Comments
 (0)