UNPKG

@tanstack/solid-router

Version:

Modern and scalable routing for Solid applications

126 lines 5.1 kB
import * as Solid from 'solid-js'; import { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'; import { isServer } from '@tanstack/router-core/isServer'; import { CatchBoundary, ErrorComponent } from './CatchBoundary'; import { useRouter } from './useRouter'; import { Transitioner } from './Transitioner'; import { nearestMatchContext } from './matchContext'; import { SafeFragment } from './SafeFragment'; import { Match } from './Match'; const NearestMatchContext = nearestMatchContext; export function Matches() { const router = useRouter(); // When disableGlobalCatchBoundary is true, we must NOT wrap with Solid.Loading // because Solid.Loading transforms STATUS_ERROR into STATUS_PENDING, which // prevents errors from propagating to an external Errored boundary. const ResolvedSuspense = router.options.disableGlobalCatchBoundary || (isServer ?? router.isServer) || (typeof document !== 'undefined' && router.ssr) ? SafeFragment : Solid.Loading; const rootRoute = () => router.routesById[rootRouteId]; const PendingComponent = rootRoute().options.pendingComponent ?? router.options.defaultPendingComponent; const OptionalWrapper = router.options.InnerWrap || SafeFragment; return (<OptionalWrapper> <ResolvedSuspense fallback={PendingComponent ? <PendingComponent /> : null}> <Transitioner /> <MatchesInner /> </ResolvedSuspense> </OptionalWrapper>); } function MatchesInner() { const router = useRouter(); const matchId = () => router.stores.firstMatchId.state; const routeId = () => (matchId() ? rootRouteId : undefined); const match = () => routeId() ? router.stores.getMatchStoreByRouteId(rootRouteId).state : undefined; const hasPendingMatch = () => routeId() ? Boolean(router.stores.pendingRouteIds.state[rootRouteId]) : false; const resetKey = () => router.stores.loadedAt.state; const nearestMatch = { matchId, routeId, match, hasPending: hasPendingMatch, }; const matchContent = () => (<Solid.Show when={matchId()}> <Match matchId={matchId()}/> </Solid.Show>); if (router.options.disableGlobalCatchBoundary) { // When disableGlobalCatchBoundary is true, render without any internal // error boundary so errors bubble up freely to an external Errored boundary. return (<NearestMatchContext value={nearestMatch}> {matchContent()} </NearestMatchContext>); } return (<NearestMatchContext value={nearestMatch}> <CatchBoundary getResetKey={() => resetKey()} errorComponent={ErrorComponent} onCatch={process.env.NODE_ENV !== 'production' ? (error) => { console.warn(`Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`); console.warn(`Warning: ${error.message || error.toString()}`); } : undefined}> {matchContent()} </CatchBoundary> </NearestMatchContext>); } export function useMatchRoute() { const router = useRouter(); return (opts) => { return Solid.createMemo(() => { const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts; router.stores.matchRouteReactivity.state; return router.matchRoute(rest, { pending, caseSensitive, fuzzy, includeSearch, }); }); }; } export function MatchRoute(props) { const matchRoute = useMatchRoute(); const params = matchRoute(props); const renderedChild = Solid.createMemo(() => { const matchedParams = params(); const child = props.children; if (typeof child === 'function') { return child(matchedParams); } return matchedParams ? child : null; }); return <>{renderedChild()}</>; } export function useMatches(opts) { const router = useRouter(); return Solid.createMemo((prev) => { const matches = router.stores.activeMatchesSnapshot.state; const res = opts?.select ? opts.select(matches) : matches; if (prev === undefined) return res; return replaceEqualDeep(prev, res); }); } export function useParentMatches(opts) { const contextMatchId = Solid.useContext(nearestMatchContext).matchId; return useMatches({ select: (matches) => { matches = matches.slice(0, matches.findIndex((d) => d.id === contextMatchId())); return opts?.select ? opts.select(matches) : matches; }, }); } export function useChildMatches(opts) { const contextMatchId = Solid.useContext(nearestMatchContext).matchId; return useMatches({ select: (matches) => { matches = matches.slice(matches.findIndex((d) => d.id === contextMatchId()) + 1); return opts?.select ? opts.select(matches) : matches; }, }); } //# sourceMappingURL=Matches.jsx.map