@tanstack/vue-router
Version:
Modern and scalable routing for Vue applications
46 lines • 2.25 kB
JSX
import * as Vue from 'vue';
import { useRouterState } from './useRouterState';
import { injectDummyMatch, injectMatch } from './matchContext';
export function useMatch(opts) {
const nearestMatchId = opts.from ? injectDummyMatch() : injectMatch();
// Store to track pending error for deferred throwing
const pendingError = Vue.ref(null);
// Select the match from router state
const matchSelection = useRouterState({
select: (state) => {
const match = state.matches.find((d) => opts.from ? opts.from === d.routeId : d.id === nearestMatchId.value);
if (match === undefined) {
// During navigation transitions, check if the match exists in pendingMatches
const pendingMatch = state.pendingMatches?.find((d) => opts.from ? opts.from === d.routeId : d.id === nearestMatchId.value);
// If there's a pending match or we're transitioning, return undefined without throwing
if (pendingMatch || state.isTransitioning) {
pendingError.value = null;
return undefined;
}
// Store the error to throw later if shouldThrow is enabled
if (opts.shouldThrow ?? true) {
pendingError.value = new Error(`Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
}
return undefined;
}
pendingError.value = null;
return opts.select ? opts.select(match) : match;
},
});
// Throw the error if we have one - this happens after the selector runs
// Using a computed so the error is thrown when the return value is accessed
const result = Vue.computed(() => {
// Check for pending error first
if (pendingError.value) {
throw pendingError.value;
}
return matchSelection.value;
});
// Also immediately throw if there's already an error from initial render
// This ensures errors are thrown even if the returned ref is never accessed
if (pendingError.value) {
throw pendingError.value;
}
return result;
}
//# sourceMappingURL=useMatch.jsx.map