Skip to content

Conversation

Sheraff
Copy link
Contributor

@Sheraff Sheraff commented Aug 18, 2025

Fix #4971 (comment)

With the code now simplified by previous PRs, we noticed that the shouldExecuteBeforeLoad guard is always true, so we can clean it up.

In a follow up PR, we'll revise the conditions under which a beforeLoad should be called or skipped.

Summary by CodeRabbit

  • Refactor

    • Streamlined pre-load checks and execution flow, reducing branching and improving consistency across client and server rendering.
    • Unified orchestration of the before-load phase to simplify control flow and improve maintainability.
  • Bug Fixes

    • More reliable handling of redirects and “not found” states during preloading, preventing unintended execution paths and improving navigation stability.

Copy link

coderabbitai bot commented Aug 18, 2025

Walkthrough

Refactors beforeLoad orchestration in load-matches.ts: consolidates server-check logic, renames and changes signature of a precondition function, replaces boolean gating with promise-based setup and execution, simplifies redirect/notFound handling during preload, and maintains SSR semantics while altering control flow to use the new pre-execution setup.

Changes

Cohort / File(s) Summary
BeforeLoad orchestration refactor
packages/router-core/src/load-matches.ts
Consolidated server-check in shouldSkipLoader; replaced shouldExecuteBeforeLoad with preBeforeLoadSetup (void/Promise<void)); shifted early-return logic to setup; simplified preload redirect/notFound handling; reworked handleBeforeLoad to run preBeforeLoadSetup then execute() unconditionally; preserved SSR semantics with new gating path.

Sequence Diagram(s)

sequenceDiagram
  participant Router
  participant loadMatches
  participant preBeforeLoadSetup
  participant execute as execute(beforeLoad)
  participant Redirect as handleRedirectAndNotFound

  Router->>loadMatches: start load
  loadMatches->>preBeforeLoadSetup: prepare (SSR checks, preload setup)
  preBeforeLoadSetup-->>loadMatches: resolve (no boolean)
  loadMatches->>execute: run beforeLoad
  execute-->>loadMatches: result (status)
  alt preload and redirected/notFound
    loadMatches->>Redirect: handle redirect/notFound
  end
  loadMatches-->>Router: done
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • schiller-manuel

Poem

I thump my paw—preflight’s neat and tight,
No booleans hop, just promises alight.
BeforeLoad bounds, then execution flows,
Redirects only when the preload knows.
In SSR burrows, pathways unify—
A tidier trail where packets fly. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor-router-core-cleanup-post-refactor

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

nx-cloud bot commented Aug 18, 2025

View your CI Pipeline Execution ↗ for commit 0dcac36

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 4m 39s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 32s View ↗

☁️ Nx Cloud last updated this comment at 2025-08-18 19:41:54 UTC

Copy link

pkg-pr-new bot commented Aug 18, 2025

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@4992

@tanstack/directive-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@4992

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@4992

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@4992

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@4992

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@4992

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@4992

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@4992

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@4992

@tanstack/react-start-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-plugin@4992

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@4992

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@4992

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@4992

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@4992

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@4992

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@4992

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@4992

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@4992

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@4992

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@4992

@tanstack/server-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@4992

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@4992

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@4992

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@4992

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@4992

@tanstack/solid-start-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-plugin@4992

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@4992

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@4992

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@4992

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@4992

@tanstack/start-server-functions-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-client@4992

@tanstack/start-server-functions-fetcher

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-fetcher@4992

@tanstack/start-server-functions-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-functions-server@4992

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@4992

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@4992

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@4992

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@4992

commit: 0dcac36

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/router-core/src/load-matches.ts (2)

331-335: Optional: also wait for an ongoing loader when coordinating with previous work

Right now you only await a previous beforeLoad. If a prior in-flight loader (without a beforeLoad) is the thing that sets redirected/notFound, the then() check may run too early to observe that status. If that’s not intentional, consider awaiting the loader as well:

-  // Wait for the previous beforeLoad to resolve before we continue
-  return existingMatch._nonReactive.beforeLoadPromise
-    ? existingMatch._nonReactive.beforeLoadPromise.then(then)
-    : then()
+  // Wait for prior beforeLoad (or, if present, an ongoing loader) before continuing
+  const p =
+    existingMatch._nonReactive.beforeLoadPromise ??
+    existingMatch._nonReactive.loaderPromise
+  return p ? p.then(then) : then()

Please confirm the intended semantics: is it acceptable for a new beforeLoad to proceed without waiting for an in-flight loader from a previous cycle?


492-494: Nit: define execute before it’s referenced to reduce cognitive load

queueExecution references execute; while the call site order currently ensures execute is defined before queueExecution runs, placing execute first avoids accidental TDZ bugs if this block is refactored later.

-  const queueExecution = () => {
-    if (shouldSkipLoader(inner, matchId)) return
-    const result = preBeforeLoadSetup(inner, matchId, route)
-    return isPromise(result) ? result.then(execute) : execute()
-  }
-
-  const execute = () => executeBeforeLoad(inner, matchId, index, route)
+  const execute = () => executeBeforeLoad(inner, matchId, index, route)
+
+  const queueExecution = () => {
+    if (shouldSkipLoader(inner, matchId)) return
+    const result = preBeforeLoadSetup(inner, matchId, route)
+    return isPromise(result) ? result.then(execute) : execute()
+  }

Also applies to: 496-497

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f2190d7 and 0dcac36.

📒 Files selected for processing (1)
  • packages/router-core/src/load-matches.ts (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/router-core/src/load-matches.ts (2)
packages/router-core/src/index.ts (1)
  • AnyRoute (163-163)
packages/router-core/src/utils.ts (1)
  • isPromise (467-475)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (2)
packages/router-core/src/load-matches.ts (2)

150-152: Simplified server-side skip condition looks correct

Combining the server and ssr=false checks into a single condition preserves behavior and is easier to read. The 'data-only' case remains unaffected.


304-309: Renaming and signature change improve intent clarity

Switching from shouldExecuteBeforeLoad to preBeforeLoadSetup and returning void | Promise matches the new orchestration where execution is unconditional post-setup. Early-return when no in-flight load is also correct.

Comment on lines 322 to 329
const match = inner.router.getMatch(matchId)!
if (match.status === 'error') {
result = true
} else if (
if (
match.preload &&
(match.status === 'redirected' || match.status === 'notFound')
) {
handleRedirectAndNotFound(inner, match, match.error)
}
return result
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Guard against missing match after preload redirect to avoid runtime crash

In preload flows, a prior beforeLoad/loader can redirect and the match may no longer exist in router.state. Accessing match.preload/status via a non-null assertion can crash at runtime.

Apply a defensive check before dereferencing:

-    const match = inner.router.getMatch(matchId)!
-    if (
+    const match = inner.router.getMatch(matchId)
+    if (!match) return
+    if (
       match.preload &&
       (match.status === 'redirected' || match.status === 'notFound')
     ) {
       handleRedirectAndNotFound(inner, match, match.error)
     }

I can add a regression test that preloads a route whose beforeLoad redirects, ensuring no crash here. Want me to open a follow-up?

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const match = inner.router.getMatch(matchId)!
if (match.status === 'error') {
result = true
} else if (
if (
match.preload &&
(match.status === 'redirected' || match.status === 'notFound')
) {
handleRedirectAndNotFound(inner, match, match.error)
}
return result
}
const match = inner.router.getMatch(matchId)
if (!match) return
if (
match.preload &&
(match.status === 'redirected' || match.status === 'notFound')
) {
handleRedirectAndNotFound(inner, match, match.error)
}
🤖 Prompt for AI Agents
In packages/router-core/src/load-matches.ts around lines 322 to 329, the code
dereferences match with a non-null assertion after getting it from
inner.router.getMatch(matchId), which can crash if a prior beforeLoad/loader
redirected and removed the match; add a defensive check for match existence and
only proceed to check match.preload and match.status if match is defined (e.g.,
if (!match) continue/return), otherwise skip calling handleRedirectAndNotFound;
update control flow so handleRedirectAndNotFound is only invoked when match !==
undefined.

@Sheraff Sheraff merged commit 5134aa2 into main Aug 19, 2025
6 checks passed
@Sheraff Sheraff deleted the refactor-router-core-cleanup-post-refactor branch August 19, 2025 06:43
tannerlinsley pushed a commit that referenced this pull request Aug 26, 2025
Fix #4971 (comment)

With the code now simplified by previous PRs, we noticed that the
`shouldExecuteBeforeLoad` guard is always true, so we can clean it up.

In a follow up PR, we'll revise the conditions under which a
`beforeLoad` should be called or skipped.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Streamlined pre-load checks and execution flow, reducing branching and
improving consistency across client and server rendering.
* Unified orchestration of the before-load phase to simplify control
flow and improve maintainability.

* **Bug Fixes**
* More reliable handling of redirects and “not found” states during
preloading, preventing unintended execution paths and improving
navigation stability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant