1import { NavigationRouteContext, ParamListBase, RouteProp } from '@react-navigation/native'; 2import React from 'react'; 3 4import { store, useStoreRootState, useStoreRouteInfo } from './global-state/router-store'; 5import { Router } from './types'; 6 7type SearchParams = Record<string, string | string[]>; 8 9export function useRootNavigationState() { 10 return useStoreRootState(); 11} 12 13export function useRouteInfo() { 14 return useStoreRouteInfo(); 15} 16 17export function useRootNavigation() { 18 return store.navigationRef.current; 19} 20 21export function useRouter(): Router { 22 return React.useMemo( 23 () => ({ 24 push: store.push, 25 back: store.goBack, 26 replace: store.replace, 27 setParams: store.setParams, 28 canGoBack: store.canGoBack, 29 // TODO(EvanBacon): add `reload` 30 }), 31 [] 32 ); 33} 34 35/** 36 * @private 37 * @returns the current global pathname with query params attached. This may change in the future to include the hostname from a predefined universal link, i.e. `/foobar?hey=world` becomes `https://acme.dev/foobar?hey=world` 38 */ 39export function useUnstableGlobalHref(): string { 40 return useStoreRouteInfo().unstable_globalHref; 41} 42 43/** 44 * Get a list of selected file segments for the currently selected route. Segments are not normalized, so they will be the same as the file path. e.g. /[id]?id=normal -> ["[id]"] 45 * 46 * `useSegments` can be typed using an abstract. 47 * Consider the following file structure, and strictly typed `useSegments` function: 48 * 49 * ```md 50 * - app 51 * - [user] 52 * - index.js 53 * - followers.js 54 * - settings.js 55 * ``` 56 * This can be strictly typed using the following abstract: 57 * 58 * ```ts 59 * const [first, second] = useSegments<['settings'] | ['[user]'] | ['[user]', 'followers']>() 60 * ``` 61 */ 62export function useSegments<TSegments extends string[] = string[]>(): TSegments { 63 return useStoreRouteInfo().segments as TSegments; 64} 65 66/** @returns global selected pathname without query parameters. */ 67export function usePathname(): string { 68 return useStoreRouteInfo().pathname; 69} 70 71/** 72 * Get the globally selected query parameters, including dynamic path segments. This function will update even when the route is not focused. 73 * Useful for analytics or other background operations that don't draw to the screen. 74 * 75 * When querying search params in a stack, opt-towards using `useLocalSearchParams` as these will only 76 * update when the route is focused. 77 * 78 * @see `useLocalSearchParams` 79 */ 80export function useGlobalSearchParams< 81 TParams extends SearchParams = SearchParams, 82>(): Partial<TParams> { 83 return useStoreRouteInfo().params as Partial<TParams>; 84} 85 86/** 87 * Returns the URL search parameters for the contextually focused route. e.g. `/acme?foo=bar` -> `{ foo: "bar" }`. 88 * This is useful for stacks where you may push a new screen that changes the query parameters. 89 * 90 * To observe updates even when the invoking route is not focused, use `useGlobalSearchParams()`. 91 */ 92export function useLocalSearchParams< 93 TParams extends SearchParams = SearchParams, 94>(): Partial<TParams> { 95 return (useOptionalLocalRoute()?.params ?? ({} as any)) as Partial<TParams>; 96} 97 98function useOptionalLocalRoute<T extends RouteProp<ParamListBase>>(): T | undefined { 99 const route = React.useContext(NavigationRouteContext); 100 return route as T | undefined; 101} 102