-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Which project does this relate to?
Router
Describe the bug
When using a declarative mask on search parameters, the prev
argument in the mask’s search
function contains search values from the previously active route instead of the search parameters defined on the clicked Link
.
More precisely, the search
function runs 4 times upon clicking on the masked route's Link
.
- For the first two,
prev
contains search values from the previously active route. - For the next 2, it contains the search parameters defined on the currently clicked
Link
.
However, the resulting URL reflects the values from the first two calls (the stale route’s parameters), rather than the intended values from the clicked Link
.
Mask
const homeMask = createRouteMask({
routeTree,
from: "/other",
to: "/other",
search: (prev) => {
// The timestamp is used to emphasize the console output, it is otherwise not needed.
const timestamp = new Date();
let val = prev.query + " " + timestamp.getMinutes() + "minutes" + " " + timestamp.getSeconds() +"seconds";
console.log(val);
return {
...prev,
query: val,
hasDiscount: undefined,
};
},
});
Links
<Link
to="/profile"
search={{
query: "profile",
hasDiscount: true,
}}
>
Prof
</Link>
<Link
to="/other"
search={{
query: "other",
hasDiscount: true,
}}
>
other
</link>
Type validation (same for both routes)
export const Route = createFileRoute("/profile")({
component: RouteComponent,
validateSearch: ({ query, hasDiscount }): ret => {
return {
query: query as string | undefined,
hasDiscount: hasDiscount as boolean | undefined,
};
},
});
Your Example Website or App
https://stackblitz.com/edit/vitejs-vite-4dj9qsmg?file=src%2FApp.tsx
Steps to Reproduce the Bug or Issue
- After opening the link, open the preview in a new tab using the top right button (Cannot see the url otherwise).
- Click on the
Profile
Link - Open the console and clear it
- Click on the
Other
Link. - Observe:
- The url contains
.../other?query=profile...
- The console logs 4 outputs, two from the mask running on the
profile
route and 2 outputs from the mask running on theother
route. All 4 outputs ran at the same time.
- The url contains
Expected behavior
The url should instead contain: .../other?query=other...
Instead of using the previous route's search parameters, the mask should use the parameters from the activated Link
.
Screenshots or Videos
Console logs after clicking on "profile" and after clicking on "other".

Url after clicking on "profile". (Normal, no masking)

Url after clicking on "other". (Masking, but with value of profile)

Platform
- Router Version: 1.131.31
- Browser: Chrome, Firefox
- React Version: 19.1.1
- Bundler: vite
- Bundler Version: 7.1.3
Additional context
The documentation for masking only includes a full example for masking using path parameters. The documentation also does not mention this specific use case. That being said, I was able to reproduce the desired behavior using imperative masking, which makes me believe this behavior is not desired.