Skip to content

Commit 2129d63

Browse files
committed
Update docs for React Navigation 8
1 parent eb01fec commit 2129d63

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2812
-3150
lines changed
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
---
2+
title: React Navigation 8.0 Alpha
3+
authors: satya
4+
tags: [announcement]
5+
---
6+
7+
We're excited to announce the first alpha release of React Navigation 8.0.
8+
9+
For this release, we tried to minimize large breaking changes when possible, and focused on improvements such as better TypeScript types, native bottom tabs as the default, and various other new features. There are many more improvements planned for the final release.
10+
11+
<!--truncate-->
12+
13+
You can read the full list of changes in the [upgrade guide](/docs/8.x/upgrading-from-7.x). Here are some highlights:
14+
15+
## Highlights
16+
17+
### Native Bottom Tabs by default
18+
19+
The Bottom Tab Navigator now uses native implementations by default on iOS and Android based on [`react-native-screens`](https://github.com/software-mansion/react-native-screens).
20+
21+
This lets us provide a native look by default, such as the new liquid glass effect on iOS 26.
22+
23+
<video playsInline autoPlay muted loop style={{ width: '500px', aspectRatio: 3 / 1 }}>
24+
25+
<source src="/assets/blog/8.x/native-bottom-tabs-ios.mp4" />
26+
</video>
27+
28+
<video playsInline autoPlay muted loop style={{ width: '500px', aspectRatio: 3 / 1 }}>
29+
30+
<source src="/assets/blog/8.x/native-bottom-tabs-android.mp4" />
31+
</video>
32+
33+
We made the native implementation the default because we believe that the default experience should be as close to platform conventions as possible.
34+
35+
However, we still include a custom JS based implementation to avoid breaking existing apps and in order to support Web. You can switch to the JS implementation by passing the `implementation` prop as `custom` to the navigator.
36+
37+
See [Bottom Tab Navigator docs](/docs/8.x/bottom-tab-navigator) for more details.
38+
39+
### Get `route`, `navigation`, and state for any parent screen
40+
41+
One of the commonly requested features has been for screens to be able to access the params for parent screens, but this had a few problems:
42+
43+
- Passing down params to child screens may lead to unnecessary re-renders when the parent params change, even when they are not needed by the child screen.
44+
- Since the param types are defined by the screen itself, having additional parent params would not be compatible with the existing type system.
45+
46+
It was necessary to manually setup React Context to pass down parent params, which was cumbersome.
47+
48+
The new screen name parameter in `useRoute` solves these problems. Now, you can access the parent route and its params directly by specifying the screen name:
49+
50+
```js
51+
const route = useRoute('Profile');
52+
53+
// Params for the 'Profile' screen
54+
console.log(route.params);
55+
```
56+
57+
Similarly, you can get the `navigation` object for any parent screen by specifying the screen name in `useNavigation`:
58+
59+
```js
60+
const navigation = useNavigation('Profile');
61+
62+
// Navigation object for the 'Profile' screen
63+
console.log(navigation);
64+
```
65+
66+
And you can get the navigation state for any parent screen by specifying the screen name in `useNavigationState`:
67+
68+
```js
69+
const focusedRoute = useNavigationState(
70+
'Profile',
71+
(state) => state.routes[state.index]
72+
);
73+
74+
// Focused route for the navigator that contains the 'Profile' screen
75+
console.log(focusedRoute);
76+
```
77+
78+
See [`useRoute`](/docs/8.x/use-route), [`useNavigation`](/docs/8.x/use-navigation), and [`useNavigationState`](/docs/8.x/use-navigation-state) for more details.
79+
80+
### Better TypeScript types for static configuration
81+
82+
In React Navigation 7, we introduced a static API to reduce boilerplate for deep linking and add automatic type inference. However, it still required manual type annotations in some cases and didn't express React Navigation's full capabilities.. So we had more work to do to get to a point that we're happy with.
83+
84+
In this release, we've built upon the static API and reworked the type inference to solve many of these issues.
85+
86+
Hooks like `useNavigation`, `useRoute`, and `useNavigationState` now automatically infer types based on the provided screen name:
87+
88+
```js
89+
const navigation = useNavigation('Profile');
90+
91+
// navigation is correctly typed as StackNavigationProp<RootStackParamList, 'Profile'>
92+
```
93+
94+
The `navigation` object will now have proper types based on navigator nesting, and will include navigator specific methods such as `openDrawer` for drawer navigators or `push` for stack navigators without requiring manual type annotations.
95+
96+
<video playsInline autoPlay muted loop data-landscape>
97+
<source src="/assets/blog/8.x/use-navigation.mp4" />
98+
</video>
99+
100+
The `useRoute` hook now returns an union of all route types in the project when no screen name is provided, so it can be used in reusable components while still providing type safety.
101+
102+
It will return the appropriate route type when a screen name is specified:
103+
104+
```js
105+
const route = useRoute('Profile');
106+
107+
// route is correctly typed as RouteProp<RootStackParamList, 'Profile'>
108+
```
109+
110+
<video playsInline autoPlay muted loop data-landscape>
111+
<source src="/assets/blog/8.x/use-route.mp4" />
112+
</video>
113+
114+
Similarly, the `useNavigationState` hook will infer the correct state type for the navigator that contains the specified screen:
115+
116+
```js
117+
const focusedRoute = useNavigationState(
118+
'Profile',
119+
(state) => state.routes[state.index]
120+
);
121+
122+
// state is correctly typed as StackNavigationState<RootStackParamList>
123+
```
124+
125+
In addition, previously, the type of the `route` object couldn't be inferred in screen callbacks, listener callbacks, etc. This made it difficult to use route params in these callbacks.
126+
127+
The new `createXScreen` helper functions address this:
128+
129+
```js
130+
const Stack = createStackNavigator({
131+
screens: {
132+
Profile: createStackScreen({
133+
screen: ProfileScreen,
134+
options: ({ route }) => {
135+
const userId = route.params.userId;
136+
137+
return {
138+
title: `${userId}'s profile`
139+
};
140+
},
141+
});
142+
}
143+
});
144+
```
145+
146+
Here, the type of `route.params` is correctly inferred based on the type annotation of `ProfileScreen`.
147+
148+
Not only that, but it also infers types based on the path pattern in the `linking` configuration specified for the screen:
149+
150+
```js
151+
const Stack = createStackNavigator({
152+
screens: {
153+
Profile: createStackScreen({
154+
screen: ProfileScreen,
155+
linking: {
156+
path: 'profile/:userId',
157+
parse: {
158+
userId: (userId) => Number(userId),
159+
},
160+
},
161+
});
162+
}
163+
});
164+
```
165+
166+
In this case, React Navigation can automatically infer that `userId` is a param of type `number` based on `:userId` in the path pattern and the return type of `userId` in the `parse` config. This is inspired by how [TanStack Router infers types based on the URL pattern](https://tanstack.com/router/latest/docs/framework/solid/decisions-on-dx#declaring-the-router-instance-for-type-inference).
167+
168+
<video playsInline autoPlay muted loop data-landscape>
169+
<source src="/assets/blog/8.x/params-types.mp4" />
170+
</video>
171+
172+
Each navigator exports its own helper function, e.g. `createNativeStackScreen` for Native Stack Navigator, `createBottomTabScreen` for Bottom Tab Navigator, `createDrawerScreen` for Drawer Navigator etc.
173+
174+
With all of these improvements, it's technically possible to write an app without any manual type annotations for React Navigation, since we can infer the route type from path pattern and param parsing logic, and return correct type for `navigation` object, `route` object, and navigation state based on the screen name and navigation structure automatically.
175+
176+
See [TypeScript docs](/docs/8.x/typescript) and [Static configuration docs](/docs/8.x/static-configuration) for more details.
177+
178+
### Pushing history entries without pushing new screens
179+
180+
Traditionally, the only way to add a new entry to the history stack was by pushing a new screen. But it's not always desirable, as it adds an entirely new instance of the screen component and shows transition animations.
181+
182+
For many scenarios, we may want to add a new history entry without pushing a new screen. Such as:
183+
184+
- A product listing page with filters, where changing filters should create a new history entry so that users can go back to previous filter states.
185+
- A screen with a custom modal component, where the modal is not a separate screen in the navigator, but its state should be reflected in the URL and history.
186+
187+
The new `pushParams` API makes this possible. You can now push an entry to the history stack by adding new params without needing to push a new screen. Then the back button will update the screen to the previous params instead of going back a screen.
188+
189+
<video playsInline autoPlay muted loop data-landscape style={{ '--ifm-global-radius': '10px' }}>
190+
191+
<source src="/assets/blog/8.x/push-params.mp4" />
192+
</video>
193+
194+
This is especially important on the web, where users expect that changing certain UI states should create a new history entry, so that they can use the browser back and forward buttons to navigate through these states.
195+
196+
See [`pushParams` docs](/docs/8.x/navigation-object#pushparams) for more details.
197+
198+
### Support for `PlatformColor`, `DynamicColorIOS` and CSS custom properties in theme colors
199+
200+
Previously, React Navigation's theming system only supported string color values. In this release, we've added support for platform-specific dynamic colors such as `PlatformColor` and `DynamicColorIOS` on native, as well as CSS custom properties on the web.
201+
202+
This makes it easier to use system colors as well as share colors across native components and React Navigation components.
203+
204+
```js
205+
const MyTheme = {
206+
...DefaultTheme,
207+
colors: Platform.select({
208+
ios: () => ({
209+
primary: PlatformColor('systemRed'),
210+
background: PlatformColor('systemGroupedBackground'),
211+
// ...
212+
}),
213+
android: () => ({
214+
primary: PlatformColor('@android:color/system_primary_light'),
215+
// ...
216+
}),
217+
default: () => DefaultTheme.colors,
218+
})(),
219+
};
220+
```
221+
222+
However, there's one limitation: with string colors, React Navigation can automatically adjust colors in some scenarios (e.g. adjust the text color based on background color), which is not possible with dynamic colors. So it will fallback to pre-defined colors according to the theme in these cases.
223+
224+
See [Themes docs](/docs/8.x/themes) for more details.
225+
226+
### Other improvements and fixes
227+
228+
Many other notable improvements are:
229+
230+
- Many of the components now rely less on layout measurements to improve scenarios where the window maybe resized frequently, such as macOS and iPadOS 26.
231+
- The header and header buttons have been redesigned to match the new iOS 26 design.
232+
- Deep link configuration no longer requires an explicit [`prefixes`](/docs/8.x/navigation-container#linkingprefixes) option and handles common URL schemes automatically.
233+
- Deep links to screens behind conditional rendering can now be handled with [`routeNamesChangeBehavior`](/docs/8.x/auth-flow#handling-deep-links-after-auth).
234+
235+
## Plans for the final release
236+
237+
This is just the first alpha release of React Navigation 8.0. Some of the plans for the final release include:
238+
239+
- API to handle insets for navigation elements such as headers and tab bars
240+
- Show Navigation events in React Navigation Devtools
241+
- Improve accessibility on Web by utilizing [`inert`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert)
242+
- Integrate [`Activity`](https://react.dev/reference/react/Activity) for inactive screens
243+
244+
## Try it out
245+
246+
If you'd like to try it out, add `@alpha` to the package you're installing. For example:
247+
248+
```sh npm2yarn
249+
npm install @react-navigation/native@alpha @react-navigation/bottom-tabs@alpha
250+
```
251+
252+
Your feedback is very important to us to ensure a smooth final release. If you encounter any issues or have any feedback or suggestions, please let us know on [GitHub issues](https://github.com/react-navigation/react-navigation/issues) or our [GitHub Discussions forum](https://github.com/react-navigation/react-navigation/discussions).
253+
254+
## Special thanks
255+
256+
React Navigation 8 would not have been possible without our amazing contributors.
257+
258+
Thanks a lot to [Michał Osadnik](https://x.com/mosdnk), [Kacper Kafara](https://x.com/kafara_kacper), [Krzysztof Ligarski](https://github.com/kligarski), [Tomasz Boroń](https://github.com/t0maboro), [Konrad Michalik](https://github.com/kmichalikk), [Oskar Kwaśniewski](https://github.com/okwasniewski) and many others for their contributions to this release.
259+
260+
And a big thanks to [Callstack](https://callstack.com/) for funding the development of many of these features!
261+
262+
## Sponsor us
263+
264+
If React Navigation helps you to deliver value to your customers, it'd mean a lot if you could sponsor us. Sponsorships will help us to move more quickly towards our goal of building the best cross-platform navigation library and continue to provide timely support for bug reports in our GitHub issues.
265+
266+
👉 [Visit our GitHub Sponsors page](https://github.com/sponsors/react-navigation) 👈

src/components/Pre.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ export default function Pre({
152152
const version = activeVersion?.name;
153153

154154
if (version == null || versions[version] == null) {
155-
throw new Error(`Invalid version: ${version}`);
155+
console.warn(
156+
`No version information found for version "${version}", cannot resolve Snack dependencies automatically.`
157+
);
158+
159+
return <FocusedCodeBlock {...rest}>{children}</FocusedCodeBlock>;
156160
}
157161

158162
Object.assign(

src/css/custom.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,10 +607,6 @@ samp {
607607
display: none;
608608
}
609609

610-
.markdown li > p {
611-
margin-bottom: 0;
612-
}
613-
614610
.video-player {
615611
position: relative;
616612
display: inline-block;
81.8 KB
Binary file not shown.
1.49 MB
Binary file not shown.
963 KB
Binary file not shown.
100 KB
Binary file not shown.
851 KB
Binary file not shown.
618 KB
Binary file not shown.

versioned_docs/version-8.x/auth-flow.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ Example scenario:
949949
- The app shows the `SignIn` screen.
950950
- After the user signs in, you want to navigate them to the `Profile` screen.
951951

952-
To achieve this, you can set [`UNSTABLE_routeNamesChangeBehavior`](navigator.md#route-names-change-behavior) to `"lastUnhandled"`:
952+
To achieve this, you can set [`routeNamesChangeBehavior`](navigator.md#route-names-change-behavior) to `"lastUnhandled"`:
953953

954954
:::warning
955955

@@ -963,7 +963,7 @@ This API is experimental and may change in a minor release.
963963
```js
964964
const RootStack = createNativeStackNavigator({
965965
// highlight-next-line
966-
UNSTABLE_routeNamesChangeBehavior: 'lastUnhandled',
966+
routeNamesChangeBehavior: 'lastUnhandled',
967967
screens: {
968968
Home: {
969969
if: useIsSignedIn,
@@ -986,7 +986,7 @@ const RootStack = createNativeStackNavigator({
986986
```js
987987
<Stack.Navigator
988988
// highlight-next-line
989-
UNSTABLE_routeNamesChangeBehavior="lastUnhandled"
989+
routeNamesChangeBehavior="lastUnhandled"
990990
>
991991
{isSignedIn ? (
992992
<Stack.Screen name="Home" component={HomeScreen} />
@@ -999,4 +999,4 @@ const RootStack = createNativeStackNavigator({
999999
</TabItem>
10001000
</Tabs>
10011001

1002-
The `UNSTABLE_routeNamesChangeBehavior` option allows you to control how React Navigation handles navigation when the available screens change because of conditions such as authentication state. When `lastUnhandled` is specified, React Navigation will remember the last screen that couldn't be handled, and after the condition changes, it'll automatically navigate to that screen if it's now available.
1002+
The `routeNamesChangeBehavior` option allows you to control how React Navigation handles navigation when the available screens change because of conditions such as authentication state. When `lastUnhandled` is specified, React Navigation will remember the last screen that couldn't be handled, and after the condition changes, it'll automatically navigate to that screen if it's now available.

0 commit comments

Comments
 (0)