UNPKG

1.58 kBTypeScriptView Raw
1import type {
2 NavigationState,
3 ParamListBase,
4 Route,
5} from '@react-navigation/routers';
6import * as React from 'react';
7
8import type { RouteProp } from './types';
9
10type RouteCache = Map<Route<string>, RouteProp<ParamListBase>>;
11
12/**
13 * Utilites such as `getFocusedRouteNameFromRoute` need to access state.
14 * So we need a way to suppress the warning for those use cases.
15 * This is fine since they are internal utilities and this is not public API.
16 */
17export const CHILD_STATE = Symbol('CHILD_STATE');
18
19/**
20 * Hook to cache route props for each screen in the navigator.
21 * This lets add warnings and modifications to the route object but keep references between renders.
22 */
23export default function useRouteCache<State extends NavigationState>(
24 routes: State['routes']
25) {
26 // Cache object which holds route objects for each screen
27 const cache = React.useMemo(() => ({ current: new Map() as RouteCache }), []);
28
29 if (process.env.NODE_ENV === 'production') {
30 // We don't want the overhead of creating extra maps every render in prod
31 return routes;
32 }
33
34 cache.current = routes.reduce((acc, route) => {
35 const previous = cache.current.get(route);
36
37 if (previous) {
38 // If a cached route object already exists, reuse it
39 acc.set(route, previous);
40 } else {
41 const { state, ...proxy } = route;
42
43 Object.defineProperty(proxy, CHILD_STATE, {
44 enumerable: false,
45 value: state,
46 });
47
48 acc.set(route, proxy);
49 }
50
51 return acc;
52 }, new Map() as RouteCache);
53
54 return Array.from(cache.current.values());
55}