TanStack / router

🤖 Fully typesafe Router for React (and friends) w/ built-in caching, 1st class search-param APIs, client-side cache integration and isomorphic rendering.
https://tanstack.com/router
MIT License
8.18k stars 643 forks source link

Infinite redirects when throwing a redirect with `to: '.'` #2418

Open mirague opened 1 month ago

mirague commented 1 month ago

Which project does this relate to?

Router

Describe the bug

We used to be able to throw a redirect to update the route params, like so:

// This was both type-safe and working before a few versions ago, now it's still working but _not_ type-safe:
throw redirect({ 
  from: Route.fullPath,
  params: (params) => ({ ...params, id: newId }),
})

This actually still works at runtime but no longer type checks since a few TSR versions back, we're expected to pass the to: '.' to get loose types:

// TS is happy with this, but you'll be in a world of hurt trying to load this page... 🥶
throw redirect({ 
  from: Route.fullPath,
  to: '.',
  params: (params) => ({ ...params, id: newId }),
})

However, throwing a redirect with a to of '.' and updating just a route param causes an infinite redirect loop, causing the browser tab to freeze to a halt.

Known workarounds for this is:

Your Example Website or App

https://stackblitz.com/edit/tanstack-router-uyaeym?file=src%2Froutes%2Fusers.%24id.tsx

Steps to Reproduce the Bug or Issue

  1. Go to the page
  2. Press [Go to Logged in User]
  3. Your browser tab is now stuck in an infinite redirect loop

Expected behavior

I expect to be able to throw a redirect to only update the route params. According to the docs we can make the type checks happy by passing to: '.', but this affects the runtime behaviour.

Screenshots or Videos

No response

Platform

macOS, Arc 1.61

Additional context

No response

schiller-manuel commented 1 month ago

the infinite loop is definitely a bug, we'll look into it. however, based on your descriptiont I would expect that you are only throwing such a redirect using your helper function if the route /users/$id is matched. So I would set from: '/users/$id' in that helper.

mirague commented 1 month ago

the infinite loop is definitely a bug, we'll look into it. however, based on your descriptiont I would expect that you are only throwing such a redirect using your helper function if the route /users/$id is matched. So I would set from: '/users/$id' in that helper.

You are right that my example is a bit skewed, I wanted to keep the repro as simple as possible. In the blitzstack you can easily omit the to: '.' and it will work as expected, but that doesn't carry over very well when moving the throw redirect to a generic guard/helper where the from isn't necessarily known, or at best a string type.