about summary refs log tree commit diff
path: root/src/lib/hooks/useNavigationDeduped.ts
blob: 99efad61052ca74e6239e1d82d74fe896f95e23e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import {useNavigation} from '@react-navigation/core'
import {NavigationState} from '@react-navigation/native'
import type {NavigationAction} from '@react-navigation/routers'
import {useDedupe} from 'lib/hooks/useDedupe'
import {AllNavigatorParams, NavigationProp} from 'lib/routes/types'
import React from 'react'

export type DebouncedNavigationProp = Pick<
  NavigationProp,
  | 'popToTop'
  | 'push'
  | 'navigate'
  | 'canGoBack'
  | 'replace'
  | 'dispatch'
  | 'goBack'
  | 'getState'
>

export function useNavigationDeduped() {
  const navigation = useNavigation<NavigationProp>()
  const dedupe = useDedupe()

  return React.useMemo(
    (): DebouncedNavigationProp => ({
      // Types from @react-navigation/routers/lib/typescript/src/StackRouter.ts
      push: <RouteName extends keyof AllNavigatorParams>(
        ...args: undefined extends AllNavigatorParams[RouteName]
          ?
              | [screen: RouteName]
              | [screen: RouteName, params: AllNavigatorParams[RouteName]]
          : [screen: RouteName, params: AllNavigatorParams[RouteName]]
      ) => {
        dedupe(() => navigation.push(...args))
      },
      // Types from @react-navigation/core/src/types.tsx
      navigate: <RouteName extends keyof AllNavigatorParams>(
        ...args: RouteName extends unknown
          ? undefined extends AllNavigatorParams[RouteName]
            ?
                | [screen: RouteName]
                | [screen: RouteName, params: AllNavigatorParams[RouteName]]
            : [screen: RouteName, params: AllNavigatorParams[RouteName]]
          : never
      ) => {
        dedupe(() => navigation.navigate(...args))
      },
      // Types from @react-navigation/routers/lib/typescript/src/StackRouter.ts
      replace: <RouteName extends keyof AllNavigatorParams>(
        ...args: undefined extends AllNavigatorParams[RouteName]
          ?
              | [screen: RouteName]
              | [screen: RouteName, params: AllNavigatorParams[RouteName]]
          : [screen: RouteName, params: AllNavigatorParams[RouteName]]
      ) => {
        dedupe(() => navigation.replace(...args))
      },
      dispatch: (
        action:
          | NavigationAction
          | ((state: NavigationState) => NavigationAction),
      ) => {
        dedupe(() => navigation.dispatch(action))
      },
      popToTop: () => {
        dedupe(() => navigation.popToTop())
      },
      goBack: () => {
        dedupe(() => navigation.goBack())
      },
      canGoBack: () => {
        return navigation.canGoBack()
      },
      getState: () => {
        return navigation.getState()
      },
    }),
    [dedupe, navigation],
  )
}