UNPKG

@tanstack/react-router

Version:

Modern and scalable routing for React applications

1 lines 6.76 kB
{"version":3,"file":"useMatch.cjs","names":[],"sources":["../../src/useMatch.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { invariant, replaceEqualDeep } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { dummyMatchContext, matchContext } from './matchContext'\nimport { useRouter } from './useRouter'\nimport type {\n StructuralSharingOption,\n ValidateSelected,\n} from './structuralSharing'\nimport type {\n AnyRouter,\n MakeRouteMatch,\n MakeRouteMatchUnion,\n RegisteredRouter,\n StrictOrFrom,\n ThrowConstraint,\n ThrowOrOptional,\n} from '@tanstack/router-core'\n\nconst dummyStore = {\n get() {},\n subscribe() {\n return { unsubscribe() {} }\n },\n} as any\n\nexport function useStructuralSharing<\n TRouter extends AnyRouter,\n TSelected,\n TStructuralSharing extends boolean,\n TStoreSlice,\n TSelectSlice = TStoreSlice,\n>(\n opts:\n | {\n select?: (\n slice: TSelectSlice,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n structuralSharing?: boolean\n }\n | undefined,\n router: TRouter,\n): (\n slice: TStoreSlice,\n) => ValidateSelected<TRouter, TSelected, TStructuralSharing> {\n const previousResult =\n // @ts-expect-error -- init to undefined, but without writing `undefined` to shave bytes\n React.useRef<ValidateSelected<TRouter, TSelected, TStructuralSharing>>()\n\n return (slice) => {\n const selected = opts?.select\n ? opts.select(slice as unknown as TSelectSlice)\n : (slice as ValidateSelected<TRouter, TSelected, TStructuralSharing>)\n\n if (opts?.structuralSharing ?? router.options.defaultStructuralSharing) {\n return (previousResult.current = replaceEqualDeep(\n previousResult.current,\n selected,\n ))\n }\n\n return selected\n }\n}\n\nexport interface UseMatchBaseOptions<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TThrow extends boolean,\n TSelected,\n TStructuralSharing extends boolean,\n> {\n select?: (\n match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n shouldThrow?: TThrow\n}\n\nexport type UseMatchRoute<out TFrom> = <\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchBaseOptions<\n TRouter,\n TFrom,\n true,\n true,\n TSelected,\n TStructuralSharing\n > &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n) => UseMatchResult<TRouter, TFrom, true, TSelected>\n\nexport type UseMatchOptions<\n TRouter extends AnyRouter,\n TFrom extends string | undefined,\n TStrict extends boolean,\n TThrow extends boolean,\n TSelected,\n TStructuralSharing extends boolean,\n> = StrictOrFrom<TRouter, TFrom, TStrict> &\n UseMatchBaseOptions<\n TRouter,\n TFrom,\n TStrict,\n TThrow,\n TSelected,\n TStructuralSharing\n > &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>\n\nexport type UseMatchResult<\n TRouter extends AnyRouter,\n TFrom,\n TStrict extends boolean,\n TSelected,\n> = unknown extends TSelected\n ? TStrict extends true\n ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>\n : MakeRouteMatchUnion<TRouter>\n : TSelected\n\n/**\n * Read and select the nearest or targeted route match.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchHook\n */\nexport function useMatch<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string | undefined = undefined,\n TStrict extends boolean = true,\n TThrow extends boolean = true,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts: UseMatchOptions<\n TRouter,\n TFrom,\n TStrict,\n ThrowConstraint<TStrict, TThrow>,\n TSelected,\n TStructuralSharing\n >,\n): ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow> {\n const router = useRouter<TRouter>()\n const nearestMatchId = React.useContext(\n opts.from ? dummyMatchContext : matchContext,\n )\n\n const matchStore = opts.from\n ? router.stores.getRouteMatchStore(opts.from)\n : router.stores.matchStores.get(nearestMatchId!)\n\n if (isServer ?? router.isServer) {\n const match = matchStore?.get()\n if (!match) {\n if (opts.shouldThrow ?? true) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n }\n\n invariant()\n }\n\n return undefined as any\n }\n\n return (opts.select ? opts.select(match as any) : match) as any\n }\n\n const selector =\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n useStructuralSharing(opts, router)\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n const matchSelection = useStore(matchStore ?? dummyStore, (match) =>\n match ? selector(match as any) : dummyStore,\n )\n\n if (matchSelection !== dummyStore) {\n return matchSelection\n }\n\n if (opts.shouldThrow ?? true) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Invariant failed: Could not find ${opts.from ? `an active match from \"${opts.from}\"` : 'a nearest match!'}`,\n )\n }\n\n invariant()\n }\n\n return undefined as any\n}\n"],"mappings":";;;;;;;;;;AAsBA,IAAM,aAAa;CACjB,MAAM,CAAC;CACP,YAAY;EACV,OAAO,EAAE,cAAc,CAAC,EAAE;CAC5B;AACF;AAEA,SAAgB,qBAOd,MAQA,QAG4D;CAC5D,MAAM,iBAEJ,MAAM,OAAiE;CAEzE,QAAQ,UAAU;EAChB,MAAM,WAAW,MAAM,SACnB,KAAK,OAAO,KAAgC,IAC3C;EAEL,IAAI,MAAM,qBAAqB,OAAO,QAAQ,0BAC5C,OAAQ,eAAe,WAAA,GAAA,sBAAA,kBACrB,eAAe,SACf,QACF;EAGF,OAAO;CACT;AACF;;;;;AAiEA,SAAgB,SAQd,MAQ6E;CAC7E,MAAM,SAAS,kBAAA,UAAmB;CAClC,MAAM,iBAAiB,MAAM,WAC3B,KAAK,OAAO,qBAAA,oBAAoB,qBAAA,YAClC;CAEA,MAAM,aAAa,KAAK,OACpB,OAAO,OAAO,mBAAmB,KAAK,IAAI,IAC1C,OAAO,OAAO,YAAY,IAAI,cAAe;CAEjD,IAAI,+BAAA,YAAY,OAAO,UAAU;EAC/B,MAAM,QAAQ,YAAY,IAAI;EAC9B,IAAI,CAAC,OAAO;GACV,IAAI,KAAK,eAAe,MAAM;IAC5B,IAAA,QAAA,IAAA,aAA6B,cAC3B,MAAM,IAAI,MACR,oCAAoC,KAAK,OAAO,yBAAyB,KAAK,KAAK,KAAK,oBAC1F;IAGF,CAAA,GAAA,sBAAA,WAAU;GACZ;GAEA;EACF;EAEA,OAAQ,KAAK,SAAS,KAAK,OAAO,KAAY,IAAI;CACpD;CAEA,MAAM,WAEJ,qBAAqB,MAAM,MAAM;CAGnC,MAAM,kBAAA,GAAA,sBAAA,UAA0B,cAAc,aAAa,UACzD,QAAQ,SAAS,KAAY,IAAI,UACnC;CAEA,IAAI,mBAAmB,YACrB,OAAO;CAGT,IAAI,KAAK,eAAe,MAAM;EAC5B,IAAA,QAAA,IAAA,aAA6B,cAC3B,MAAM,IAAI,MACR,oCAAoC,KAAK,OAAO,yBAAyB,KAAK,KAAK,KAAK,oBAC1F;EAGF,CAAA,GAAA,sBAAA,WAAU;CACZ;AAGF"}