Skip to content

Commit 29bcc59

Browse files
committed
Improve custom navigator docs
1 parent 585978d commit 29bcc59

File tree

1 file changed

+51
-11
lines changed

1 file changed

+51
-11
lines changed

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

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,60 @@ title: Custom navigators
44
sidebar_label: Custom navigators
55
---
66

7-
Navigators allow you to define your application's navigation structure. Navigators also render common elements such as headers and tab bars which you can configure.
7+
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.
88

9-
Under the hood, navigators are plain React components.
9+
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.
1010

11-
## Built-in Navigators
11+
A custom navigator behaves just like a built-in navigator, and can be used in the same way. This means you can define screens the same way, use [route](route-object.md) and [navigation](navigation-prop.md) objects in your screens, and navigate between screens with familiar API. The navigator will also be able to handle deep linking, state persistence, and other features that built-in navigators support.
1212

13-
We include some commonly needed navigators such as:
13+
## Overview
1414

15-
- [`createStackNavigator`](stack-navigator.md) - Renders one screen at a time and provides transitions between screens. When a new screen is opened it is placed on top of the stack.
16-
- [`createDrawerNavigator`](drawer-navigator.md) - Provides a drawer that slides in from the left of the screen by default.
17-
- [`createBottomTabNavigator`](bottom-tab-navigator.md) - Renders a tab bar that lets the user switch between several screens.
18-
- [`createMaterialTopTabNavigator`](material-top-tab-navigator.md) - Renders tab view which lets the user switch between several screens using swipe gesture or the tab bar.
15+
Under the hood, navigators are plain React components that use the [`useNavigationBuilder`](#usenavigationbuilder) hook.
1916

20-
## API for building custom navigators
17+
The navigator component then uses this state to layout the screens appropriately with any additional UI based on the use case. This component is then wrapped in [`createNavigatorFactory`](#createnavigatorfactory) to create the API for the navigator.
2118

22-
A navigator bundles a router and a view which takes the [navigation state](navigation-state.md) and decides how to render it. We export a `useNavigationBuilder` hook to build custom navigators that integrate with rest of React Navigation.
19+
A very basic example looks like this:
20+
21+
```js
22+
function MyStackNavigator(props) {
23+
const { state, descriptors, NavigationContent } = useNavigationBuilder(
24+
StackRouter,
25+
props
26+
);
27+
28+
const focusedRoute = state.routes[state.index];
29+
const descriptor = descriptors[focusedRoute.key];
30+
31+
return <NavigationContent>{descriptor.render()}</NavigationContent>;
32+
}
33+
34+
export const createMyStackNavigator = createNavigatorFactory(MyStackNavigator);
35+
```
36+
37+
Now, we have an already working navigator, even though it doesn't do anything special yet.
38+
39+
Let's break this down:
40+
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.
42+
- 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.
43+
- 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.
44+
- 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.
45+
- Then we get the corresponding descriptor for the focused route with `descriptors[focusedRoute.key]` and call the `render()` method on it to get the React element for the screen.
46+
- The content of the navigator is wrapped in `NavigationContent` to provide appropriate context and wrappers.
47+
48+
With this, we have a basic stack navigator that renders only the focused screen. Unlike the built-in stack navigator, this doesn't keep unfocused screens rendered. But you can loop through `state.routes` and render all of the screens if you want to keep them mounted. You can also read `descriptor.options` to get the [options](screen-options.md) to handle the screen's title, header, and other options.
49+
50+
This also doesn't have any additional UI apart from the screen content. There are no gestures or animations. So you're free to add any additional UI, gestures, animations etc. as needed. You can also layout the screens in any way you want, such as rendering them side-by-side or in a grid, instead of stacking them on top of each other like the built-in stack navigator does.
51+
52+
You can see a more complete example of a custom navigator later in this document.
53+
54+
## API Definition
2355

2456
### `useNavigationBuilder`
2557

26-
This hook allows a component to hook into React Navigation. It accepts the following arguments:
58+
This hook contains the core logic of a navigator, and is responsible for storing and managing the [navigation state](navigation-state.md). It takes a [router](custom-routers.md) as an argument to know how to handle various navigation actions. It then returns the state and helper methods for the navigator component to use.
59+
60+
It accepts the following arguments:
2761

2862
- `createRouter` - A factory method which returns a router object (e.g. `StackRouter`, `TabRouter`).
2963
- `options` - Options for the hook and the router. The navigator should forward its props here so that user can provide props to configure the navigator. By default, the following options are accepted:
@@ -140,6 +174,12 @@ export function createMyNavigator(config) {
140174
}
141175
```
142176
177+
:::note
178+
179+
We can also do `export const createMyNavigator = createNavigatorFactory(MyNavigator)` directly instead of wrapping in another function. However, the wrapper function is necessary to have proper [TypeScript support](#type-checking-navigators) for the navigator.
180+
181+
:::
182+
143183
Then it can be used like this:
144184
145185
```js

0 commit comments

Comments
 (0)