60 lines
1.8 KiB
Plaintext
60 lines
1.8 KiB
Plaintext
import { useStore } from '@tanstack/react-store'
|
|
import { useRef } from 'react'
|
|
import { replaceEqualDeep } from '@tanstack/router-core'
|
|
import { useRouter } from './useRouter'
|
|
import type {
|
|
AnyRouter,
|
|
RegisteredRouter,
|
|
RouterState,
|
|
} from '@tanstack/router-core'
|
|
import type {
|
|
StructuralSharingOption,
|
|
ValidateSelected,
|
|
} from './structuralSharing'
|
|
|
|
export type UseRouterStateOptions<
|
|
TRouter extends AnyRouter,
|
|
TSelected,
|
|
TStructuralSharing,
|
|
> = {
|
|
router?: TRouter
|
|
select?: (
|
|
state: RouterState<TRouter['routeTree']>,
|
|
) => ValidateSelected<TRouter, TSelected, TStructuralSharing>
|
|
} & StructuralSharingOption<TRouter, TSelected, TStructuralSharing>
|
|
|
|
export type UseRouterStateResult<
|
|
TRouter extends AnyRouter,
|
|
TSelected,
|
|
> = unknown extends TSelected ? RouterState<TRouter['routeTree']> : TSelected
|
|
|
|
export function useRouterState<
|
|
TRouter extends AnyRouter = RegisteredRouter,
|
|
TSelected = unknown,
|
|
TStructuralSharing extends boolean = boolean,
|
|
>(
|
|
opts?: UseRouterStateOptions<TRouter, TSelected, TStructuralSharing>,
|
|
): UseRouterStateResult<TRouter, TSelected> {
|
|
const contextRouter = useRouter<TRouter>({
|
|
warn: opts?.router === undefined,
|
|
})
|
|
const router = opts?.router || contextRouter
|
|
const previousResult =
|
|
useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>(undefined)
|
|
|
|
return useStore(router.__store, (state) => {
|
|
if (opts?.select) {
|
|
if (opts.structuralSharing ?? router.options.defaultStructuralSharing) {
|
|
const newSlice = replaceEqualDeep(
|
|
previousResult.current,
|
|
opts.select(state),
|
|
)
|
|
previousResult.current = newSlice
|
|
return newSlice
|
|
}
|
|
return opts.select(state)
|
|
}
|
|
return state
|
|
}) as UseRouterStateResult<TRouter, TSelected>
|
|
}
|