remix: Cannot redirect to different app on same domain from loader function
What version of Remix are you using?
1.5.1
Steps to Reproduce
I have a Remix Form that submits a GET request to a UI-route’s loader function, which can either return a JSON object or redirect the user to different places depending on the value of a query parameter.
For instance, these are the 2 only properties that I set on my Remix Form:
<Form method="get" action="/product-A">...</Form>
Let’s say the domain of my application is mywebsite.com, and when the form is submitted the query looks like this: mywebsite.com/product-A?area=11103.
The loader function has 3 possible outcomes:
- return
json(payload)and renders the UI-route. This works ✅ - redirect user to an external website through
redirect('differenwebsite.com'). This works ✅ - redirect user to
mywebsite.com/product-B, which is a route on the same domain that is handled by a separate NextJS application. This doesn’t work, Remix shows a 404 page undermywebsite.com/product-B❌
In order to make the Form work in every scenario, I’d have to use the reloadDocument property, but that would be detrimental for the “happy path” UX.
Expected Behavior
I’d expect loader functions to be able to redirect to routes that live on the same domain, even though those routes are not part of the Remix application.
I’d expect to do so without resorting to the use of the reloadDocument directive on the Form.
Actual Behavior
Remix shows a 404 error page when a Form submission to a loader function results into a redirection to a route that is handled by a different application on the same domain.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 16 (8 by maintainers)
Any progress on this issue?
This code is what’s causing the issue. It checks the redirect URL’s origin and compares it to the current location. If the same, then it simply does a client side transition.
Perhaps, they could support adding a header
X-Remix-Force-Redirect: true, that will dowindow.location.replace()like for external URLs.https://github.com/remix-run/remix/blob/99d98bd85897fcb37f4bd1e22f778d7c4d89198d/packages/remix-react/routes.tsx#L212-L234
I’m not sure how to write a test for this, nor do I know if this introduces other issues. But I have tested in my application and this seems to work for my use-case.
https://github.com/remix-run/remix/compare/dev...robbtraister:feature/manifest-aware-redirects
This is one of those API changes where it’s best to actually implement as a patch and see how it works before committing to it in the core. Looks like someone has already started an implementation https://github.com/remix-run/remix/issues/3765#issuecomment-1187962950
@iliketomatoes I think that’s a great question (and the kind of thing I meant by “other issues”). The worst-case is that 404 pages are reloaded from the server. This could be problematic if you have shared state or components at a global level.
We could also make it opt-in with something like
<RemixBrowser reloadUnmatchedRedirects />Remix would still need a header or something to indicate you want to deviate from standard redirect. Sure, it would be annoying to have to add that header manually, but I don’t think it’s advisable to update the standard function to handle this edge case. Instead create a new function to encapsulate that logic.
@kiliman thanks for pointing that out!
I wonder if –instead of explicitly dealing with Remix headers– we could benefit from an extra parameter passed to the
redirectfunction, like this:Although I know, developers start giving side-looks when they see a function that has more than 2 parameters 😄
I’m also wondering if my issue is part of a bigger issue that should be solved in a more general way, see this discussion: https://github.com/remix-run/remix/discussions/1880.