@tanstack/react-router
Version:
Modern and scalable routing for React applications
99 lines (98 loc) • 3.23 kB
JavaScript
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