UNPKG

@tanstack/solid-router

Version:

Modern and scalable routing for Solid applications

106 lines 4.29 kB
import * as Solid from 'solid-js'; import { getLocationChangeInfo, handleHashScroll, trimPathRight, } from '@tanstack/router-core'; import { isServer } from '@tanstack/router-core/isServer'; import { useRouter } from './useRouter'; export function Transitioner() { const router = useRouter(); let mountLoadForRouter = { router, mounted: false }; const isLoading = Solid.createMemo(() => router.stores.isLoading.state); if (isServer ?? router.isServer) { return null; } const [isSolidTransitioning, startSolidTransition] = Solid.useTransition(); // Track pending state changes const hasPendingMatches = Solid.createMemo(() => router.stores.hasPendingMatches.state); const isAnyPending = Solid.createMemo(() => isLoading() || isSolidTransitioning() || hasPendingMatches()); const isPagePending = Solid.createMemo(() => isLoading() || hasPendingMatches()); router.startTransition = (fn) => { Solid.startTransition(() => { startSolidTransition(fn); }); }; // Subscribe to location changes // and try to load the new location Solid.onMount(() => { const unsub = router.history.subscribe(router.load); const nextLocation = router.buildLocation({ to: router.latestLocation.pathname, search: true, params: true, hash: true, state: true, _includeValidateSearch: true, }); // Check if the current URL matches the canonical form. // Compare publicHref (browser-facing URL) for consistency with // the server-side redirect check in router.beforeLoad. if (trimPathRight(router.latestLocation.publicHref) !== trimPathRight(nextLocation.publicHref)) { router.commitLocation({ ...nextLocation, replace: true }); } Solid.onCleanup(() => { unsub(); }); }); // Try to load the initial location Solid.createRenderEffect(() => { Solid.untrack(() => { if ( // if we are hydrating from SSR, loading is triggered in ssr-client (typeof window !== 'undefined' && router.ssr) || (mountLoadForRouter.router === router && mountLoadForRouter.mounted)) { return; } mountLoadForRouter = { router, mounted: true }; const tryLoad = async () => { try { await router.load(); } catch (err) { console.error(err); } }; tryLoad(); }); }); Solid.createRenderEffect((previousIsLoading = false) => { const currentIsLoading = isLoading(); if (previousIsLoading && !currentIsLoading) { router.emit({ type: 'onLoad', ...getLocationChangeInfo(router.stores.location.state, router.stores.resolvedLocation.state), }); } return currentIsLoading; }); Solid.createComputed((previousIsPagePending = false) => { const currentIsPagePending = isPagePending(); if (previousIsPagePending && !currentIsPagePending) { router.emit({ type: 'onBeforeRouteMount', ...getLocationChangeInfo(router.stores.location.state, router.stores.resolvedLocation.state), }); } return currentIsPagePending; }); Solid.createRenderEffect((previousIsAnyPending = false) => { const currentIsAnyPending = isAnyPending(); if (previousIsAnyPending && !currentIsAnyPending) { const changeInfo = getLocationChangeInfo(router.stores.location.state, router.stores.resolvedLocation.state); router.emit({ type: 'onResolved', ...changeInfo, }); Solid.batch(() => { router.stores.status.setState(() => 'idle'); router.stores.resolvedLocation.setState(() => router.stores.location.state); }); if (changeInfo.hrefChanged) { handleHashScroll(router); } } return currentIsAnyPending; }); return null; } //# sourceMappingURL=Transitioner.jsx.map