Skip to content

Commit 73e30ad

Browse files
committed
Update documentation for custom navigators
1 parent 06d9ed2 commit 73e30ad

2 files changed

Lines changed: 28 additions & 95 deletions

File tree

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

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -169,17 +169,9 @@ import {
169169

170170
// ...
171171

172-
export function createMyNavigator(config) {
173-
return createNavigatorFactory(TabNavigator)(config);
174-
}
172+
export const createMyNavigator = createNavigatorFactory(MyNavigator);
175173
```
176174
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-
183175
Then it can be used like this:
184176
185177
```js static2dynamic
@@ -225,22 +217,17 @@ import {
225217
} from 'react-native';
226218
import {
227219
createNavigatorFactory,
220+
createScreenFactory,
228221
CommonActions,
229222
type DefaultNavigatorOptions,
223+
type NavigationProp,
230224
type NavigatorTypeBagBase,
231225
type ParamListBase,
232-
type StaticConfig,
233-
type StaticParamList,
234-
type StaticScreenConfig,
235-
type StaticScreenConfigLinking,
236-
type StaticScreenConfigScreen,
237226
type TabActionHelpers,
238227
type TabNavigationState,
239228
TabRouter,
240229
type TabRouterOptions,
241-
type TypedNavigator,
242230
useNavigationBuilder,
243-
type NavigationProp,
244231
} from '@react-navigation/native';
245232

246233
// Additional props accepted by the view
@@ -347,49 +334,29 @@ function TabNavigator({ tabBarStyle, contentStyle, ...rest }: Props) {
347334
);
348335
}
349336

350-
// Types required for type-checking the navigator
351-
type MyTabTypeBag<ParamList extends {}> = {
352-
ParamList: ParamList;
353-
State: TabNavigationState<ParamList>;
337+
// Type bag used for type-checking the navigator
338+
export interface MyTabTypeBag extends NavigatorTypeBagBase {
339+
State: TabNavigationState<this['ParamList']>;
354340
ScreenOptions: MyNavigationOptions;
355341
EventMap: MyNavigationEventMap;
356-
NavigationList: {
357-
[RouteName in keyof ParamList]: MyNavigationProp<ParamList, RouteName>;
358-
};
342+
ActionHelpers: TabActionHelpers<this['ParamList']>;
359343
Navigator: typeof TabNavigator;
360-
};
361-
362-
// The factory function with overloads for static and dynamic configuration
363-
export function createMyNavigator<
364-
const ParamList extends ParamListBase,
365-
>(): TypedNavigator<MyTabTypeBag<ParamList>, undefined>;
366-
export function createMyNavigator<
367-
const Config extends StaticConfig<MyTabTypeBag<ParamListBase>>,
368-
>(
369-
config: Config
370-
): TypedNavigator<MyTabTypeBag<StaticParamList<{ config: Config }>>, Config>;
371-
export function createMyNavigator(config?: unknown) {
372-
return createNavigatorFactory(TabNavigator)(config);
373344
}
374345

346+
// The factory function for creating a navigator
347+
export const createMyNavigator =
348+
createNavigatorFactory<MyTabTypeBag>(TabNavigator);
349+
375350
// Helper function for creating screen config with proper types for static configuration
376-
export function createMyScreen<
377-
const Linking extends StaticScreenConfigLinking,
378-
const Screen extends StaticScreenConfigScreen,
379-
>(
380-
config: StaticScreenConfig<
381-
Linking,
382-
Screen,
383-
TabNavigationState<ParamListBase>,
384-
MyNavigationOptions,
385-
MyNavigationEventMap,
386-
MyNavigationProp<ParamListBase>
387-
>
388-
) {
389-
return config;
390-
}
351+
export const createMyScreen = createScreenFactory<MyTabTypeBag>();
391352
```
392353
354+
:::info
355+
356+
The type bag must use an `interface` instead of `type` for `this` to work. It also needs to be exported in the public API for type inference to work.
357+
358+
:::
359+
393360
## Extending Navigators
394361
395362
All of the built-in navigators export their views, which we can reuse and build additional functionality on top of them. For example, if we want to re-build the bottom tab navigator, we need the following code:

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

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ This is technically not a breaking change. It's not required to use this API and
165165

166166
See [Static configuration docs](static-configuration.md#createxscreen) for more details.
167167

168-
#### Custom navigators now require overloads for types
168+
#### Custom navigators have a simpler type API
169169

170-
To work with the reworked TypeScript types, custom navigators now need to provide overloads for static and dynamic configuration APIs, and an additional API to create screen config.
170+
To work with the reworked TypeScript types, the type API for custom navigators has been updated. The new API uses an interface that extends `NavigatorTypeBagBase` and a pair of factory helpers - `createNavigatorFactory` and `createScreenFactory`:
171171

172172
```diff lang=ts
173173
- export function createMyNavigator<
@@ -192,54 +192,20 @@ To work with the reworked TypeScript types, custom navigators now need to provid
192192
- >(config?: Config): TypedNavigator<TypeBag, Config> {
193193
- return createNavigatorFactory(MyNavigator)(config);
194194
- }
195-
+ type MyTypeBag<ParamList extends {}> = {
196-
+ ParamList: ParamList;
197-
+ State: TabNavigationState<ParamList>;
195+
+ export interface MyTypeBag extends NavigatorTypeBagBase {
196+
+ State: TabNavigationState<this['ParamList']>;
198197
+ ScreenOptions: MyNavigationOptions;
199198
+ EventMap: MyNavigationEventMap;
200-
+ NavigationList: {
201-
+ [RouteName in keyof ParamList]: MyNavigationProp<
202-
+ ParamList,
203-
+ RouteName
204-
+ >;
205-
+ };
199+
+ ActionHelpers: TabActionHelpers<this['ParamList']>;
206200
+ Navigator: typeof MyNavigator;
207-
+ };
208-
+
209-
+ export function createMyNavigator<
210-
+ const ParamList extends ParamListBase,
211-
+ >(): TypedNavigator<MyTypeBag<ParamList>, undefined>;
212-
+ export function createMyNavigator<
213-
+ const Config extends StaticConfig<MyTypeBag<ParamListBase>>,
214-
+ >(
215-
+ config: Config
216-
+ ): TypedNavigator<
217-
+ MyTypeBag<StaticParamList<{ config: Config }>>,
218-
+ Config
219-
+ >;
220-
+ export function createMyNavigator(config?: unknown) {
221-
+ return createNavigatorFactory(MyNavigator)(config);
222-
+ }
223-
224-
+ export function createMyScreen<
225-
+ const Linking extends StaticScreenConfigLinking,
226-
+ const Screen extends StaticScreenConfigScreen,
227-
+ >(
228-
+ config: StaticScreenConfig<
229-
+ Linking,
230-
+ Screen,
231-
+ TabNavigationState<ParamListBase>,
232-
+ MyNavigationOptions,
233-
+ MyNavigationEventMap,
234-
+ MyNavigationProp<ParamListBase>
235-
+ >
236-
+ ) {
237-
+ return config;
238201
+ }
202+
+
203+
+ export const createMyNavigator =
204+
+ createNavigatorFactory<MyTypeBag>(MyNavigator);
205+
+
206+
+ export const createMyScreen = createScreenFactory<MyTypeBag>();
239207
```
240208

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

245211
### Changes to navigators

0 commit comments

Comments
 (0)