| 42 | * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useRouterStateHook |
| 43 | */ |
| 44 | export function useRouterState< |
| 45 | TRouter extends AnyRouter = RegisteredRouter, |
| 46 | TSelected = unknown, |
| 47 | TStructuralSharing extends boolean = boolean, |
| 48 | >( |
| 49 | opts?: UseRouterStateOptions<TRouter, TSelected, TStructuralSharing>, |
| 50 | ): UseRouterStateResult<TRouter, TSelected> { |
| 51 | const contextRouter = useRouter<TRouter>({ |
| 52 | warn: opts?.router === undefined, |
| 53 | }) |
| 54 | const router = opts?.router || contextRouter |
| 55 | |
| 56 | // During SSR we render exactly once and do not need reactivity. |
| 57 | // Avoid subscribing to the store (and any structural sharing work) on the server. |
| 58 | const _isServer = isServer ?? router.isServer |
| 59 | if (_isServer) { |
| 60 | const state = router.state as RouterState<TRouter['routeTree']> |
| 61 | return (opts?.select ? opts.select(state) : state) as UseRouterStateResult< |
| 62 | TRouter, |
| 63 | TSelected |
| 64 | > |
| 65 | } |
| 66 | |
| 67 | const previousResult = |
| 68 | // eslint-disable-next-line react-hooks/rules-of-hooks |
| 69 | useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(undefined) |
| 70 | |
| 71 | // eslint-disable-next-line react-hooks/rules-of-hooks |
| 72 | return useStore(router.__store, (state) => { |
| 73 | if (opts?.select) { |
| 74 | if (opts.structuralSharing ?? router.options.defaultStructuralSharing) { |
| 75 | const newSlice = replaceEqualDeep( |
| 76 | previousResult.current, |
| 77 | opts.select(state), |
| 78 | ) |
| 79 | previousResult.current = newSlice |
| 80 | return newSlice |
| 81 | } |
| 82 | return opts.select(state) |
| 83 | } |
| 84 | return state |
| 85 | }) as UseRouterStateResult<TRouter, TSelected> |
| 86 | } |