Repository: TanStack/router
Pull request #2443 (2024-09-30 10:28:08)

fix(react-router): fix matchPathname with basepath
In micro-frontend applications, host app will inject `basepath` to micro app. When the host app is navigating to its own route, the mounted micro apps will monitor and trigger redirect as well without respecting the `basepath`.

czizzy: @SeanCassiere could you please take a look at this? We're encountering a bug in our product.
braineo: @SeanCassiere we actually also encountered this problem. we have app1 and app2 running in the same pager and both of them use tanstank router.

app1 does not have `basepath` while app2 has `/app2` as `basepath` and a redirect on root router

when i navigated to href `/` (which is app1's route), it triggers the app2's redirect on `/` (which it shouldn't and it should only care about the href staring with `/app2`)
SeanCassiere: @czizzy I'm away till mid October, as such I've asked @schiller-manuel to review this PR.
nx-cloud[bot]: # ☁️ Nx Cloud Report

CI is running for commit 2393e084dbb045a3728e07fcd25d6e59ee83b769.

[📂 Click to track the progress, see the status, the terminal output, and the build insights.](https://cloud.nx.app/cipes/67046274673af465bb6c5b4a?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/32c990fa-d364-4af2-a4e1-3c241a9b1e75)
<details><summary><b>More templates</b></summary><p>

- [tanstack-router-react-example-authenticated-routes](https://pkg.pr.new/template/b14c327b-f788-43fd-b478-2b5988fbb3de)
- [tanstack-router-react-example-basic](https://pkg.pr.new/template/1db10410-0c50-4de5-b0de-236e25a376a3)
- [tanstack-router-react-example-basic-default-search-params](https://pkg.pr.new/template/7b11b4b9-20b3-4592-8f8c-8ab423ec0ca1)
- [tanstack-router-react-example-basic-file-based](https://pkg.pr.new/template/1fa0685f-0446-4337-974b-41f490f5e9db)
- [tanstack-router-react-example-basic-file-based-codesplitting](https://pkg.pr.new/template/dfbf1a8c-ab4a-4e32-a609-5999e1f94190)
- [tanstack-router-react-example-react-query](https://pkg.pr.new/template/a411ab03-a5c2-46b7-b7e5-fb0137d9fb60)
- [tanstack-router-react-example-basic-react-query-file-based](https://pkg.pr.new/template/69f43a99-da8c-4fda-9878-632572a85578)
- [tanstack-router-react-example-basic-ssr-file-based](https://pkg.pr.new/template/33e0ce0b-7413-4939-8fc3-9fa767f03d4c)
- [tanstack-router-react-example-basic-ssr-streaming-file-based](https://pkg.pr.new/template/a747270b-a595-4d61-bc47-db2058131eb3)
- [tanstack-router-react-example-basic-virtual-file-based](https://pkg.pr.new/template/2829fcbf-a292-47f0-a301-ff65865aa9cb)
- [tanstack-router-react-example-basic-virtual-inside-file-based](https://pkg.pr.new/template/fb567ca0-d5bb-4da1-993a-1bcf5a5c28f4)
- [tanstack-router-react-example-deferred-data](https://pkg.pr.new/template/66a196c6-c37e-4c22-baf8-07f2cc826387)
- [tanstack-router-react-example-kitchen-sink](https://pkg.pr.new/template/da26f1db-7cab-40e1-b9f8-a3a6a0f4cc6d)
- [tanstack-router-react-example-kitchen-sink-file-based](https://pkg.pr.new/template/3c0b101c-6048-4b70-8cfb-69704085a197)
- [tanstack-router-react-example-kitchen-sink-react-query](https://pkg.pr.new/template/acc43155-48c3-4baf-9c89-a4bc266039ee)
- [tanstack-router-react-example-kitchen-sink-react-query-file-based](https://pkg.pr.new/template/a0e4313d-98a9-4d04-a106-d5b57ea3eb14)
- [tanstack-router-react-example-large-file-based](https://pkg.pr.new/template/56d3f87a-6e9e-4569-a601-62475fd63a4e)
- [tanstack-router-react-example-location-masking](https://pkg.pr.new/template/ccdd9185-4e32-4f00-90fa-d7ab817f99a0)
- [tanstack-router-react-example-navigation-blocking](https://pkg.pr.new/template/e6abd5b6-b38e-423a-823b-8f02dd0314c6)
- [tanstack-router-react-example-quickstart](https://pkg.pr.new/template/6f3dac37-372e-4d58-9659-00e1f04e8c84)
- [tanstack-router-react-example-quickstart-file-based](https://pkg.pr.new/template/6741e9bd-f7e3-484c-a2d4-7299549830cf)
- [tanstack-router-react-example-quickstart-rspack-file-based](https://pkg.pr.new/template/3b96616e-37e7-484d-8735-69b2132a5a4f)
- [tanstack-router-react-example-quickstart-webpack-file-based](https://pkg.pr.new/template/76c9eac4-87d1-4150-a089-ad012c265975)
- [tanstack-router-react-example-scroll-restoration](https://pkg.pr.new/template/ab6cb78f-74b5-46ac-b91b-6ed34bddd418)
- [tanstack-router-search-validator-adapters](https://pkg.pr.new/template/cc0f6db2-0790-4bb3-af8b-6a29bcd70065)
- [tanstack-start-example-basic](https://pkg.pr.new/template/fb518b27-0bce-4559-a522-054f81e2744a)
- [tanstack-start-example-basic-auth](https://pkg.pr.new/template/a1261cbe-941c-4621-b09b-bb91011de522)
- [tanstack-start-example-basic-react-query](https://pkg.pr.new/template/e4a009a1-df35-479b-b9cc-ece7f3b85f8e)
- [tanstack-start-example-basic-rsc](https://pkg.pr.new/template/9427c04f-5f0d-4682-a97a-f936653cec37)
- [tanstack-start-example-clerk-basic](https://pkg.pr.new/template/ddadca3b-33f9-476a-b40d-233e18d7229c)
- [tanstack-start-example-convex-trellaux](https://pkg.pr.new/template/615d6c84-bbfa-42d8-affd-865aef59718a)
- [tanstack-start-example-counter](https://pkg.pr.new/template/a4ed55f2-5ec7-4ef4-bc35-96a7388ddb3b)
- [tanstack-start-example-supabase-basic](https://pkg.pr.new/template/6a3d36fc-cf5e-4d68-aa05-5cf9ebd67f9f)
- [tanstack-start-example-trellaux](https://pkg.pr.new/template/d5791c31-0453-456f-87cb-3f5b9690eec3)
- [tanstack-router-react-example-with-framer-motion](https://pkg.pr.new/template/b920b0ff-8480-43af-aca0-ae7900a88f5c)
- [tanstack-router-react-example-with-trpc](https://pkg.pr.new/template/dc1da400-9090-46e8-8cea-f5473abcf1fe)
- [tanstack-router-react-example-with-trpc-react-query](https://pkg.pr.new/template/ad81b25a-fe82-426e-a627-dcd7a81b7ace)

</p></details>
      
    


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

```
pnpm add https://pkg.pr.new/@tanstack/eslint-plugin-router@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/create-router@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/history@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/react-cross-context@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/react-router@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/react-router-with-query@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-arktype-adapter@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-cli@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-devtools@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-generator@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-plugin@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-vite-plugin@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-valibot-adapter@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/start@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/router-zod-adapter@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/virtual-file-routes@2443
```

</p></details>
      
    

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

```
pnpm add https://pkg.pr.new/@tanstack/start-vite-plugin@2443
```

</p></details>
      
    

_commit: <a href="https://github.com/TanStack/router/runs/31203188389"><code>2393e08</code></a>_


Patch:
diff --git a/packages/react-router/src/path.ts b/packages/react-router/src/path.ts
index c77ea0987..7569ba31b 100644
--- a/packages/react-router/src/path.ts
+++ b/packages/react-router/src/path.ts
@@ -298,6 +298,10 @@ export function matchByPath(
   from: string,
   matchLocation: Pick<MatchLocation, 'to' | 'caseSensitive' | 'fuzzy'>,
 ): Record<string, string> | undefined {
+  // check basepath first
+  if (basepath !== '/' && !from.startsWith(basepath)) {
+    return undefined
+  }
   // Remove the base path from the pathname
   from = removeBasepath(basepath, from)
   // Default to to $ (wildcard)


Test patch:
diff --git a/packages/react-router/tests/path.test.ts b/packages/react-router/tests/path.test.ts
index d77719c2a..0e9212524 100644
--- a/packages/react-router/tests/path.test.ts
+++ b/packages/react-router/tests/path.test.ts
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'
 import {
   exactPathTest,
   interpolatePath,
+  matchPathname,
   removeBasepath,
   removeTrailingSlash,
   resolvePath,
@@ -276,3 +277,57 @@ describe('interpolatePath', () => {
     })
   })
 })
+
+describe('matchPathname', () => {
+  it.each([
+    {
+      name: 'should match the root path that start with the basepath',
+      basepath: '/basepath',
+      pathname: '/basepath',
+      matchLocation: {
+        to: '/',
+      },
+      expected: {},
+    },
+    {
+      name: 'should match the path that start with the basepath',
+      basepath: '/basepath',
+      pathname: '/basepath/abc',
+      matchLocation: {
+        to: '/abc',
+      },
+      expected: {},
+    },
+    {
+      name: 'should not match the root path that does not start with the basepath',
+      basepath: '/basepath',
+      pathname: '/',
+      matchLocation: {
+        to: '/',
+      },
+      expected: undefined,
+    },
+    {
+      name: 'should not match the path that does not start with the basepath',
+      basepath: '/basepath',
+      pathname: '/abc',
+      matchLocation: {
+        to: '/abc',
+      },
+      expected: undefined,
+    },
+    {
+      name: 'should not match the path that match partial of the basepath',
+      basepath: '/base',
+      pathname: '/basepath/abc',
+      matchLocation: {
+        to: '/abc',
+      },
+      expected: undefined,
+    },
+  ])('$name', ({ basepath, pathname, matchLocation, expected }) => {
+    expect(matchPathname(basepath, pathname, matchLocation)).toStrictEqual(
+      expected,
+    )
+  })
+})