Skip to content

Commit 5608b63

Browse files
committed
Make it more defensive
1 parent 70b2b6c commit 5608b63

File tree

1 file changed

+49
-19
lines changed

1 file changed

+49
-19
lines changed

packages/react/src/reactrouter-compat-utils/instrumentation.tsx

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ export function createV6CompatibleWrapCreateBrowserRouter<
244244
// Track whether we've completed the initial pageload to properly distinguish
245245
// between POPs that occur during pageload vs. legitimate back/forward navigation.
246246
let isInitialPageloadComplete = false;
247+
let hasSeenPageloadSpan = !!activeRootSpan && spanToJSON(activeRootSpan).op === 'pageload';
248+
let hasSeenPopAfterPageload = false;
247249

248250
// The initial load ends when `createBrowserRouter` is called.
249251
// This is the earliest convenient time to update the transaction name.
@@ -259,17 +261,22 @@ export function createV6CompatibleWrapCreateBrowserRouter<
259261
}
260262

261263
router.subscribe((state: RouterState) => {
262-
// Check if pageload span has ended to mark completion
264+
// Track pageload completion to distinguish POPs during pageload from legitimate back/forward navigation
263265
if (!isInitialPageloadComplete) {
264266
const currentRootSpan = getActiveRootSpan();
265-
const isStillInPageload = currentRootSpan && spanToJSON(currentRootSpan).op === 'pageload';
267+
const isCurrentlyInPageload = currentRootSpan && spanToJSON(currentRootSpan).op === 'pageload';
266268

267-
if (!isStillInPageload) {
269+
if (isCurrentlyInPageload) {
270+
hasSeenPageloadSpan = true;
271+
} else if (!hasSeenPageloadSpan) {
272+
// No pageload span detected, so we're not in initial pageload mode
273+
isInitialPageloadComplete = true;
274+
} else if (state.historyAction === 'POP' && !hasSeenPopAfterPageload) {
275+
// Pageload ended: ignore the first POP after pageload
276+
hasSeenPopAfterPageload = true;
277+
} else {
278+
// Pageload ended: either non-POP action or subsequent POP
268279
isInitialPageloadComplete = true;
269-
// Don't handle this specific callback if it's a POP that marks completion
270-
if (state.historyAction === 'POP') {
271-
return;
272-
}
273280
}
274281
}
275282

@@ -343,7 +350,6 @@ export function createV6CompatibleWrapCreateMemoryRouter<
343350
const router = createRouterFunction(routes, wrappedOpts);
344351
const basename = opts?.basename;
345352

346-
const activeRootSpan = getActiveRootSpan();
347353
let initialEntry = undefined;
348354

349355
const initialEntries = opts?.initialEntries;
@@ -364,30 +370,46 @@ export function createV6CompatibleWrapCreateMemoryRouter<
364370
: initialEntry
365371
: router.state.location;
366372

367-
if (router.state.historyAction === 'POP' && activeRootSpan) {
368-
updatePageloadTransaction({ activeRootSpan, location, routes, basename, allRoutes: Array.from(allRoutes) });
373+
const memoryActiveRootSpan = getActiveRootSpan();
374+
375+
if (router.state.historyAction === 'POP' && memoryActiveRootSpan) {
376+
updatePageloadTransaction({
377+
activeRootSpan: memoryActiveRootSpan,
378+
location,
379+
routes,
380+
basename,
381+
allRoutes: Array.from(allRoutes),
382+
});
369383
}
370384

371385
// Track whether we've completed the initial pageload to properly distinguish
372386
// between POPs that occur during pageload vs. legitimate back/forward navigation.
373387
let isInitialPageloadComplete = false;
388+
let hasSeenPageloadSpan = !!memoryActiveRootSpan && spanToJSON(memoryActiveRootSpan).op === 'pageload';
389+
let hasSeenPopAfterPageload = false;
374390

375391
router.subscribe((state: RouterState) => {
376-
// Check if pageload span has ended to mark completion
392+
// Track pageload completion to distinguish POPs during pageload from legitimate back/forward navigation
377393
if (!isInitialPageloadComplete) {
378394
const currentRootSpan = getActiveRootSpan();
379-
const isStillInPageload = currentRootSpan && spanToJSON(currentRootSpan).op === 'pageload';
395+
const isCurrentlyInPageload = currentRootSpan && spanToJSON(currentRootSpan).op === 'pageload';
380396

381-
if (!isStillInPageload) {
397+
if (isCurrentlyInPageload) {
398+
hasSeenPageloadSpan = true;
399+
} else if (!hasSeenPageloadSpan) {
400+
// No pageload span detected, so we're not in initial pageload mode
401+
isInitialPageloadComplete = true;
402+
} else if (state.historyAction === 'POP' && !hasSeenPopAfterPageload) {
403+
// Pageload ended: ignore the first POP after pageload
404+
hasSeenPopAfterPageload = true;
405+
} else {
406+
// Pageload ended: either non-POP action or subsequent POP
382407
isInitialPageloadComplete = true;
383-
// Don't handle this specific callback if it's a POP that marks completion
384-
if (state.historyAction === 'POP') {
385-
return;
386-
}
387408
}
388409
}
389410

390411
const location = state.location;
412+
391413
const shouldHandleNavigation =
392414
state.historyAction === 'PUSH' || (state.historyAction === 'POP' && isInitialPageloadComplete);
393415

@@ -578,8 +600,16 @@ function wrapPatchRoutesOnNavigation(
578600
// Update navigation span after routes are patched
579601
const activeRootSpan = getActiveRootSpan();
580602
if (activeRootSpan && (spanToJSON(activeRootSpan) as { op?: string }).op === 'navigation') {
581-
// For memory routers, we should not access window.location; use targetPath only
582-
const pathname = isMemoryRouter ? targetPath : targetPath || WINDOW.location?.pathname;
603+
// Determine pathname based on router type
604+
let pathname: string | undefined;
605+
if (isMemoryRouter) {
606+
// For memory routers, only use targetPath
607+
pathname = targetPath;
608+
} else {
609+
// For browser routers, use targetPath or fall back to window.location
610+
pathname = targetPath || WINDOW.location?.pathname;
611+
}
612+
583613
if (pathname) {
584614
updateNavigationSpan(
585615
activeRootSpan,

0 commit comments

Comments
 (0)