UNPKG

@tanstack/react-router

Version:

Modern and scalable routing for React applications

99 lines (98 loc) 3.23 kB
import * as React from "react"; import { trimPathRight, getLocationChangeInfo, handleHashScroll } from "@tanstack/router-core"; import { usePrevious, useLayoutEffect } from "./utils.js"; import { useRouter } from "./useRouter.js"; import { useRouterState } from "./useRouterState.js"; function Transitioner() { const router = useRouter(); const mountLoadForRouter = React.useRef({ router, mounted: false }); const isLoading = useRouterState({ select: ({ isLoading: isLoading2 }) => isLoading2 }); const [isTransitioning, setIsTransitioning] = React.useState(false); const hasPendingMatches = useRouterState({ select: (s) => s.matches.some((d) => d.status === "pending"), structuralSharing: true }); const previousIsLoading = usePrevious(isLoading); const isAnyPending = isLoading || isTransitioning || hasPendingMatches; const previousIsAnyPending = usePrevious(isAnyPending); const isPagePending = isLoading || hasPendingMatches; const previousIsPagePending = usePrevious(isPagePending); if (!router.isServer) { router.startTransition = (fn) => { setIsTransitioning(true); React.startTransition(() => { fn(); setIsTransitioning(false); }); }; } React.useEffect(() => { 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 }); if (trimPathRight(router.latestLocation.href) !== trimPathRight(nextLocation.href)) { router.commitLocation({ ...nextLocation, replace: true }); } return () => { unsub(); }; }, [router, router.history]); useLayoutEffect(() => { if (typeof window !== "undefined" && router.clientSsr || mountLoadForRouter.current.router === router && mountLoadForRouter.current.mounted) { return; } mountLoadForRouter.current = { router, mounted: true }; const tryLoad = async () => { try { await router.load(); } catch (err) { console.error(err); } }; tryLoad(); }, [router]); useLayoutEffect(() => { if (previousIsLoading && !isLoading) { router.emit({ type: "onLoad", // When the new URL has committed, when the new matches have been loaded into state.matches ...getLocationChangeInfo(router.state) }); } }, [previousIsLoading, router, isLoading]); useLayoutEffect(() => { if (previousIsPagePending && !isPagePending) { router.emit({ type: "onBeforeRouteMount", ...getLocationChangeInfo(router.state) }); } }, [isPagePending, previousIsPagePending, router]); useLayoutEffect(() => { if (previousIsAnyPending && !isAnyPending) { router.emit({ type: "onResolved", ...getLocationChangeInfo(router.state) }); router.__store.setState((s) => ({ ...s, status: "idle", resolvedLocation: s.location })); handleHashScroll(router); } }, [isAnyPending, previousIsAnyPending, router]); return null; } export { Transitioner }; //# sourceMappingURL=Transitioner.js.map