Skip to content

Commit 0f32cf9

Browse files
committed
Update custom navigator docs
1 parent 0e004c7 commit 0f32cf9

File tree

1 file changed

+58
-33
lines changed

1 file changed

+58
-33
lines changed

versioned_docs/version-7.x/custom-navigators.md

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ title: Custom navigators
44
sidebar_label: Custom navigators
55
---
66

7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
710
In essence, a navigator is a React component that takes a set of screens and options, and renders them based on its [navigation state](navigation-state.md), generally with additional UI such as headers, tab bars, or drawers.
811

912
React Navigation provides a few built-in navigators, but they might not always fit your needs if you want a very custom behavior or UI. In such cases, you can build your own custom navigators using React Navigation's APIs.
@@ -19,7 +22,13 @@ The navigator component then uses this state to layout the screens appropriately
1922
A very basic example looks like this:
2023

2124
```js
22-
function MyStackNavigator(props) {
25+
import {
26+
useNavigationBuilder,
27+
createNavigatorFactory,
28+
StackRouter,
29+
} from '@react-navigation/native';
30+
31+
function MyNavigator(props) {
2332
const { state, descriptors, NavigationContent } = useNavigationBuilder(
2433
StackRouter,
2534
props
@@ -31,14 +40,14 @@ function MyStackNavigator(props) {
3140
return <NavigationContent>{descriptor.render()}</NavigationContent>;
3241
}
3342

34-
export const createMyStackNavigator = createNavigatorFactory(MyStackNavigator);
43+
export const createMyNavigator = createNavigatorFactory(MyNavigator);
3544
```
3645

3746
Now, we have an already working navigator, even though it doesn't do anything special yet.
3847

3948
Let's break this down:
4049

41-
- We define a `MyNavigator` component that contains our navigator logic. This is the component that's rendered when you render `<Stack.Navigator>` in your app with the `createMyStackNavigator` factory function.
50+
- We define a `MyNavigator` component that contains our navigator logic. This is the component that's rendered when you render the navigator in your app with the `createMyNavigator` factory function.
4251
- We use the `useNavigationBuilder` hook and pass it [`StackRouter`](custom-routers.md#built-in-routers), which would make our navigator behave like a stack navigator. Any other router such as `TabRouter`, `DrawerRouter`, or a custom router can be used here as well.
4352
- The hook returns the [navigation state](navigation-state.md) in the `state` property. This is the current state of the navigator. There's also a `descriptors` object which contains the data and helpers for each screen in the navigator.
4453
- We get the focused route from the state with `state.routes[state.index]` - as `state.index` is the index of the currently focused route in the `state.routes` array.
@@ -80,9 +89,8 @@ Example:
8089

8190
```js
8291
import * as React from 'react';
83-
import { Text, Pressable, View } from 'react-native';
92+
import { Text, Pressable, View, StyleSheet } from 'react-native';
8493
import {
85-
NavigationHelpersContext,
8694
useNavigationBuilder,
8795
TabRouter,
8896
TabActions,
@@ -180,28 +188,34 @@ We can also do `export const createMyNavigator = createNavigatorFactory(MyNaviga
180188
181189
Then it can be used like this:
182190
183-
```js
191+
```js static2dynamic
192+
import { createStaticNavigation } from '@react-navigation/native';
184193
import { createMyNavigator } from './myNavigator';
185194

186-
const My = createMyNavigator();
195+
const MyTabs = createMyNavigator({
196+
screens: {
197+
Home: HomeScreen,
198+
Feed: FeedScreen,
199+
},
200+
});
201+
202+
const Navigation = createStaticNavigation(MyTabs);
187203

188204
function App() {
189-
return (
190-
<My.Navigator>
191-
<My.Screen name="Home" component={HomeScreen} />
192-
<My.Screen name="Feed" component={FeedScreen} />
193-
</My.Navigator>
194-
);
205+
return <Navigation />;
195206
}
196207
```
197208
198209
## Type-checking navigators
199210
200-
To type-check navigators, we need to provide 3 types:
211+
To type-check navigators, we need to provide few types:
201212
202213
- Type of the props accepted by the view
203214
- Type of supported screen options
204215
- A map of event types emitted by the navigator
216+
- The type of the navigation object for each screen
217+
218+
We also need to export a function to create the navigator configuration with proper types.
205219
206220
For example, to type-check our custom tab navigator, we can do something like this:
207221
@@ -228,31 +242,32 @@ import {
228242
type TabRouterOptions,
229243
type TypedNavigator,
230244
useNavigationBuilder,
245+
type NavigationProp,
231246
} from '@react-navigation/native';
232247

233248
// Additional props accepted by the view
234-
type TabNavigationConfig = {
249+
type MyNavigationConfig = {
235250
tabBarStyle: StyleProp<ViewStyle>;
236251
contentStyle: StyleProp<ViewStyle>;
237252
};
238253

239254
// Supported screen options
240-
type TabNavigationOptions = {
255+
type MyNavigationOptions = {
241256
title?: string;
242257
};
243258

244259
// Map of event name and the type of data (in event.data)
245260
// canPreventDefault: true adds the defaultPrevented property to the
246261
// emitted events.
247-
type TabNavigationEventMap = {
262+
type MyNavigationEventMap = {
248263
tabPress: {
249264
data: { isAlreadyFocused: boolean };
250265
canPreventDefault: true;
251266
};
252267
};
253268

254269
// The type of the navigation object for each screen
255-
type TabNavigationProp<
270+
type MyNavigationProp<
256271
ParamList extends ParamListBase,
257272
RouteName extends keyof ParamList = keyof ParamList,
258273
NavigatorID extends string | undefined = undefined,
@@ -261,8 +276,8 @@ type TabNavigationProp<
261276
RouteName,
262277
NavigatorID,
263278
TabNavigationState<ParamList>,
264-
TabNavigationOptions,
265-
TabNavigationEventMap
279+
MyNavigationOptions,
280+
MyNavigationEventMap
266281
> &
267282
TabActionHelpers<ParamList>;
268283

@@ -271,21 +286,21 @@ type Props = DefaultNavigatorOptions<
271286
ParamListBase,
272287
string | undefined,
273288
TabNavigationState<ParamListBase>,
274-
TabNavigationOptions,
275-
TabNavigationEventMap,
276-
TabNavigationProp<ParamListBase>
289+
MyNavigationOptions,
290+
MyNavigationEventMap,
291+
MyNavigationProp<ParamListBase>
277292
> &
278293
TabRouterOptions &
279-
TabNavigationConfig;
294+
MyNavigationConfig;
280295

281296
function TabNavigator({ tabBarStyle, contentStyle, ...rest }: Props) {
282297
const { state, navigation, descriptors, NavigationContent } =
283298
useNavigationBuilder<
284299
TabNavigationState<ParamListBase>,
285300
TabRouterOptions,
286301
TabActionHelpers<ParamListBase>,
287-
TabNavigationOptions,
288-
TabNavigationEventMap
302+
MyNavigationOptions,
303+
MyNavigationEventMap
289304
>(TabRouter, rest);
290305

291306
return (
@@ -337,18 +352,30 @@ function TabNavigator({ tabBarStyle, contentStyle, ...rest }: Props) {
337352
);
338353
}
339354

340-
// The factory function with generic types for type-inference
355+
// Types required for type-checking the navigator
356+
type MyTabTypeBag<ParamList extends {}> = {
357+
ParamList: ParamList;
358+
State: TabNavigationState<ParamList>;
359+
ScreenOptions: MyNavigationOptions;
360+
EventMap: MyNavigationEventMap;
361+
NavigationList: {
362+
[RouteName in keyof ParamList]: MyNavigationProp<ParamList, RouteName>;
363+
};
364+
Navigator: typeof TabNavigator;
365+
};
366+
367+
// The factory function with overloads for static and dynamic configuration
341368
export function createMyNavigator<
342369
const ParamList extends ParamListBase,
343370
const NavigatorID extends string | undefined = undefined,
344371
const TypeBag extends NavigatorTypeBagBase = {
345372
ParamList: ParamList;
346373
NavigatorID: NavigatorID;
347374
State: TabNavigationState<ParamList>;
348-
ScreenOptions: TabNavigationOptions;
349-
EventMap: TabNavigationEventMap;
375+
ScreenOptions: MyNavigationOptions;
376+
EventMap: MyNavigationEventMap;
350377
NavigationList: {
351-
[RouteName in keyof ParamList]: TabNavigationProp<
378+
[RouteName in keyof ParamList]: MyNavigationProp<
352379
ParamList,
353380
RouteName,
354381
NavigatorID
@@ -376,7 +403,6 @@ import {
376403
import { BottomTabView } from '@react-navigation/bottom-tabs';
377404

378405
function BottomTabNavigator({
379-
id,
380406
initialRouteName,
381407
children,
382408
layout,
@@ -388,7 +414,6 @@ function BottomTabNavigator({
388414
}) {
389415
const { state, descriptors, navigation, NavigationContent } =
390416
useNavigationBuilder(TabRouter, {
391-
id,
392417
initialRouteName,
393418
children,
394419
layout,
@@ -411,7 +436,7 @@ function BottomTabNavigator({
411436
}
412437

413438
export function createMyNavigator(config) {
414-
return createNavigatorFactory(TabNavigator)(config);
439+
return createNavigatorFactory(BottomTabNavigator)(config);
415440
}
416441
```
417442

0 commit comments

Comments
 (0)