Repository: TanStack/router
Pull request #2949 (2024-12-07 23:47:59)

fix(react-router): when ongoing beforeLoad failed, retry next time

nx-cloud[bot]: # ☁️ Nx Cloud Report

CI is running for commit 3c0369d67e0ab1d8cfb5274677a8a8bbd3ee1a5b.

[📂 Click to track the progress, see the status, the terminal output, and the build insights.](https://cloud.nx.app/cipes/6754dec998f9363462bb8e62?utm_source=pull-request&utm_medium=comment)


---

Sent with 💌 from [NxCloud.](https://nx.app?utm_source=pull-request&utm_medium=comment)
pkg-pr-new[bot]: 
[Open in Stackblitz](https://pkg.pr.new/template/96355f15-0ddd-48a3-9fe1-ea29b709e3aa)
<details><summary><b>More templates</b></summary><p>

- [tanstack-router-react-example-authenticated-routes](https://pkg.pr.new/template/f3e87353-c4ac-4812-88ee-72926b9d930f)
- [tanstack-router-react-example-basic](https://pkg.pr.new/template/aca70a3e-dc90-412d-be44-395bf6220ab3)
- [tanstack-router-react-example-basic-default-search-params](https://pkg.pr.new/template/463f96ff-1980-4bfb-81b6-cbed489e0a86)
- [tanstack-router-react-example-basic-file-based](https://pkg.pr.new/template/11695948-95f9-40ab-a282-242eb0c8492c)
- [tanstack-router-react-example-basic-file-based-codesplitting](https://pkg.pr.new/template/b3090cb4-ca94-4167-8e18-5c97aa5864d4)
- [tanstack-router-react-example-basic-react-query-file-based](https://pkg.pr.new/template/bc97bff4-0e31-4d32-acc6-64fff685db9b)
- [tanstack-router-react-example-react-query](https://pkg.pr.new/template/3d93ff19-ab94-4168-b171-aebfd31d4f8d)
- [tanstack-router-react-example-basic-ssr-file-based](https://pkg.pr.new/template/4202117e-3303-46af-add0-a19f9f6a0dc6)
- [tanstack-router-react-example-basic-ssr-streaming-file-based](https://pkg.pr.new/template/b0ab5f96-0c7e-4af8-8331-7ef4e355b623)
- [tanstack-router-react-example-basic-virtual-file-based](https://pkg.pr.new/template/0dcd204f-76cb-45b0-b4b7-a3910c084481)
- [tanstack-router-react-example-basic-virtual-inside-file-based](https://pkg.pr.new/template/c0de6e1d-eb43-4752-a705-113de843e619)
- [tanstack-router-react-example-deferred-data](https://pkg.pr.new/template/122a8e81-b6f9-47fa-9879-c365fc7cd780)
- [tanstack-router-react-example-kitchen-sink](https://pkg.pr.new/template/d878cc94-1e37-4652-8ae5-585b948b1704)
- [tanstack-router-react-example-kitchen-sink-file-based](https://pkg.pr.new/template/17536bcc-0176-43c7-8341-1f92342d9118)
- [tanstack-router-react-example-kitchen-sink-react-query](https://pkg.pr.new/template/215e3850-f8bc-4fe3-841b-d27761433a9d)
- [tanstack-router-react-example-kitchen-sink-react-query-file-based](https://pkg.pr.new/template/762eb532-5ca6-4eda-af14-63ed101cdd51)
- [tanstack-router-react-example-large-file-based](https://pkg.pr.new/template/13d70a10-277f-4644-8ac9-fc445c27ee0f)
- [tanstack-router-react-example-location-masking](https://pkg.pr.new/template/499acf7e-c5eb-45f8-a34b-6b33a88d5c37)
- [tanstack-router-react-example-navigation-blocking](https://pkg.pr.new/template/bafadeec-6832-47e1-a1fa-f9adffb65685)
- [tanstack-router-react-example-quickstart](https://pkg.pr.new/template/8b985ca5-410f-4785-bca7-445caed862aa)
- [tanstack-router-react-example-quickstart-esbuild-file-based](https://pkg.pr.new/template/28e61dd1-62fc-4cf3-9e9c-e73700e6d924)
- [tanstack-router-react-example-quickstart-file-based](https://pkg.pr.new/template/9f5ce50c-f76f-414d-a464-d11131f59a6e)
- [tanstack-router-react-example-quickstart-rspack-file-based](https://pkg.pr.new/template/7910446a-a4bd-40cf-b18d-08e75610d126)
- [tanstack-router-react-example-quickstart-webpack-file-based](https://pkg.pr.new/template/f69b5a02-1349-46e6-9be6-78499196d6a0)
- [router-monorepo-react-query](https://pkg.pr.new/template/b82073af-b96a-4ab8-86e2-f54c88869a0b)
- [router-mono-simple](https://pkg.pr.new/template/944d666a-dd58-4d30-bfc8-21ca685eab59)
- [tanstack-router-react-example-scroll-restoration](https://pkg.pr.new/template/7a6da71b-12ec-4271-b809-3f6bc91c1346)
- [tanstack-search-validator-adapters](https://pkg.pr.new/template/cc0cb3f0-4d04-44dd-b27c-8d62a703c913)
- [tanstack-start-example-basic](https://pkg.pr.new/template/6d0b0f00-76d6-4864-be24-574ac08148c4)
- [tanstack-start-example-basic-auth](https://pkg.pr.new/template/847a1640-6166-4c2f-ad5a-dd5bee19ad66)
- [tanstack-start-example-basic-react-query](https://pkg.pr.new/template/71f7c507-bb96-4a75-a8ae-9b158c9a8106)
- [tanstack-start-example-basic-rsc](https://pkg.pr.new/template/d1dfa495-d649-4cd0-b966-c9ebe475f667)
- [tanstack-start-example-clerk-basic](https://pkg.pr.new/template/72a9860d-3140-4124-a09c-78f37115ac5c)
- [tanstack-start-example-convex-trellaux](https://pkg.pr.new/template/92c40609-04df-4f08-b98c-1de3b2772e8b)
- [tanstack-start-example-counter](https://pkg.pr.new/template/8485caeb-0f56-45c8-bc03-85a033966ece)
- [tanstack-start-example-large](https://pkg.pr.new/template/d83c0e9f-62b0-4ce4-9a4c-7b7d11bac869)
- [tanstack-start-example-supabase-basic](https://pkg.pr.new/template/baa49aaa-de4f-4289-8d4b-98428ce12ba9)
- [tanstack-start-example-trellaux](https://pkg.pr.new/template/d5906eef-6e05-4254-a21a-484ec4285baa)
- [tanstack-router-react-example-with-framer-motion](https://pkg.pr.new/template/7d217988-2e8a-4cfa-9464-2992b762007a)
- [tanstack-router-react-example-with-trpc](https://pkg.pr.new/template/e925dc4f-a5c0-4273-a056-a0daace7044a)
- [tanstack-router-react-example-with-trpc-react-query](https://pkg.pr.new/template/15ada380-65ba-4032-b71a-901ee1218a1a)

</p></details>
      
    


<details><summary><b>@tanstack/arktype-adapter</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/arktype-adapter@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/history</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/history@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/eslint-plugin-router</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/react-cross-context</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/react-cross-context@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/create-router</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/create-router@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/react-router</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/react-router@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/react-router-with-query</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/react-router-with-query@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/router-cli</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/router-cli@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/router-devtools</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/router-devtools@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/router-generator</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/router-generator@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/router-plugin</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/router-plugin@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/router-vite-plugin</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/router-vite-plugin@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/start</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/start@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/start-vite-plugin</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/start-vite-plugin@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/valibot-adapter</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/valibot-adapter@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/virtual-file-routes</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/virtual-file-routes@2949
```

</p></details>
      
    

<details><summary><b>@tanstack/zod-adapter</b></summary><p>

```
npm i https://pkg.pr.new/@tanstack/zod-adapter@2949
```

</p></details>
      
    

_commit: <a href="https://github.com/TanStack/router/runs/34080848929"><code>3c0369d</code></a>_


Patch:
diff --git a/docs/framework/react/start/server-functions.md b/docs/framework/react/start/server-functions.md
index 1c910d4c7..d6106ac3a 100644
--- a/docs/framework/react/start/server-functions.md
+++ b/docs/framework/react/start/server-functions.md
@@ -96,7 +96,7 @@ greet({
 
 Server functions can be configured to validate their input data at runtime, while adding type safety. This is useful for ensuring the input is of the correct type before executing the server function, and providing more friendly error messages.
 
-This is done with the `validator` method. It will accept whatever input is passed to the server function. The value (and type) you return from this function will become the input to the passed to the actual server function handler.
+This is done with the `validator` method. It will accept whatever input is passed to the server function. The value (and type) you return from this function will become the input passed to the actual server function handler.
 
 Validators also integrate seamlessly with external validators, if you want to use something like Zod.
 
diff --git a/packages/react-router/src/router.ts b/packages/react-router/src/router.ts
index b06691bd4..fbc1d3283 100644
--- a/packages/react-router/src/router.ts
+++ b/packages/react-router/src/router.ts
@@ -2286,6 +2286,7 @@ export class Router<
                   this.options.defaultPendingComponent)
               )
 
+              let executeBeforeLoad = true
               if (
                 // If we are in the middle of a load, either of these will be present
                 // (not to be confused with `loadPromise`, which is always defined)
@@ -2304,8 +2305,10 @@ export class Router<
 
                 // Wait for the beforeLoad to resolve before we continue
                 await existingMatch.beforeLoadPromise
-              } else {
-                // If we are not in the middle of a load, start it
+                executeBeforeLoad = this.getMatch(matchId)!.status !== 'success'
+              }
+              if (executeBeforeLoad) {
+                // If we are not in the middle of a load OR the previous load failed, start it
                 try {
                   updateMatch(matchId, (prev) => ({
                     ...prev,


Test patch:
diff --git a/packages/react-router/tests/errorComponent.test.tsx b/packages/react-router/tests/errorComponent.test.tsx
index ccb9be1d4..fd6a5fa8c 100644
--- a/packages/react-router/tests/errorComponent.test.tsx
+++ b/packages/react-router/tests/errorComponent.test.tsx
@@ -81,12 +81,13 @@ describe.each([{ preload: false }, { preload: 'intent' }] as const)(
 
           expect(linkToAbout).toBeInTheDocument()
           fireEvent.mouseOver(linkToAbout)
+          fireEvent.focus(linkToAbout)
           fireEvent.click(linkToAbout)
 
           const errorComponent = await screen.findByText(
             `Error: error thrown`,
             undefined,
-            { timeout: 750 },
+            { timeout: 1500 },
           )
           expect(screen.findByText('About route content')).rejects.toThrow()
           expect(errorComponent).toBeInTheDocument()