router
router copied to clipboard
Context is undefined after redirect
Describe the bug
I use authentication, similar to Authenticated Routes example from documentation. So, when user is on /$lang page, if user is not authorised, user is been redirecting to /$lang/login page. It happens, but useRouteContext returns undefined instead of context. I set context in RouterProvider like this. If I reload the page, issue disappears
<RouterProvider
router={router}
context={{ auth, queryClient, showAppAlert }}
/>
I tested on 1.29.2, 1.30.1, 1.31.1, issue happens. I also tested on 1.26.21 and issue does not happen. I didn't test versions between 1.26.21 and 1.29.1
Your Example Website or App
https://admin.7loc.com/en
Steps to Reproduce the Bug or Issue
It happens in our live admin panel(admin panel at all is in development, but some functionality have already been implemented)
Expected behavior
Context, if it set in router provider is always available and not undefined
Screenshots or Videos
https://github.com/TanStack/router/assets/57814533/5d067867-024a-4e8b-9891-ecfd332771f7
Platform
- Version: 1.29.2-1.31.1
Additional context
No response
UPDATE.
It happens if I redirect from /$lang to /$lang/login. If I redirect from / to /$lang/login it does not happen. Also attached error, that appears in console
https://github.com/TanStack/router/assets/57814533/5566f3c8-1558-4ed2-9889-7413dfbda9a4
Redirects were broken between 1.28.2 and 1.31.1, but on the side of the Router context, nothing has changed in that area in a LONG time.
We'd need a working reproduction for us to be able to diagnose what specifically in your setup is breaking stuff for you.
Also please confirm this issue you are facing on version 1.31.3 as well.
You can create a reproduction using the Router file-based stackblitz starter.
I tried to reproduce this and wasn't able to recreate this on my end with version 1.31.3.
Here's my attempt: https://stackblitz.com/edit/github-dxj2gr
@SeanCassiere Managed to repro: https://stackblitz.com/edit/github-dxj2gr-btjqhp
I am having the same issue
https://stackblitz.com/edit/github-dxj2gr-xfuqc1
Case 1
- Access
/about
from the address bar of your browser - Redirect to
/foo
-
Cannot read properties of undefined (reading 'fn')
is displayed
Case 2
- Added
defaultGcTime: 0
tocreateRouter
options - Access Try me! from Home
-
Cannot read properties of undefined (reading 'fn')
is displayed
@mintaka2479 By any change, do you have any workaround for this issue? Because it brokes login/logout on my website. Now after login and logout I have this issue and user has to reload the page to fix it
Downgrading to 1.26.21
fixed the issue for us.
Sometimes it also happens with loaderData
Sometimes it also happens with loaderData
For us, loaderData was fixed in 1.31.6. Context is still sometimes undefined though.
I am on the latest version and contextI can reproduce in one place every time, but one time in console I see error with both content and loader data on latest version, but I don't know, may be something else caused it, because it was only one time on new version. As I use query, now I almost don't use loaderData, so, I cannot say more about it. But context issue is still happening and cause serious problems. As we still develop our app it is not a critical problem, but I hope it will be fixed soon
I am experiencing this too - when redirecting from one route to another in beforeLoad
, the context becomes undefined in the target route. It was introduced in v1.31.2.
Please recheck this.
It's possible that this was inadvertently fixed with #1559.
I'm still facing this problem.
If I redirect the context becomes undefined.
I'm on router version ^1.31.19
.
@SeanCassiere I have just tested on latest version and I am still facing this problem too
The default options have been fixed. However, if gcTime is 0, the loader’s context becomes undefined after the redirect. There is no problem with beforeLoad.
https://stackblitz.com/edit/github-dxj2gr-xfuqc1
- Access Try me! from Home.
console log
1./foo.beforeLoad context {foo: 'bar', fn: ƒ}
2./foo.beforeLoad context.fn
3./foo.loader context undefined
I don't have gcTime: 0. I have logout button. When user press on it, I remove auth token and make router.invalidate(), which causes throw redirect to login page in beforeLoad and in this moment context becomes undefined
I have just tested one more time. Issue happening only if I do throw redirect(). In logic logic I have two options.
- Url to redirect is specified in query param, in this case I do router.history.push()
- Url is not specified, in this case after logic I do throw redirect() to home page
So, when I do router.history.push it works. If I do throw redirect(), I am facing undefined context issue, nothing changed for me with the latest version
Issue also happens without router.invalidate() and etc. If I just go to home page anauthorised, what causes throw redirect() in my logic, it brakes with undefined context(video is from production build, in local build it shows like on screenshot)
https://github.com/TanStack/router/assets/57814533/9bb4eacc-e4aa-4a3e-9752-874620ae9182
I can also confirm that this is not fixed for me.
I've tried taking a stab at it since I've been facing this issue for a bit as well, but I'm hitting a wall. My issue is a bit different from the ones shared in the reproductions (can't share my code, and I haven't managed yet to create a repro), but basically context within loader (not beforeLoad, it's available there) is undefined after a redirect. My routes are like this:
- __root
- __root/_auth
- __root/_auth/_page (Layout shell)
- __root/_auth/_page/ (Index page)
- __root/_auth/_page/unauthorized (Page that redirects the user to Index)
The unauthorized page redirects users from within a beforeLoad
to the index page, but that causes the context in the index's loader to be undefined.
What I've seen is that once a redirect is executed, the first three routes are cached and retrieved from the Router's store, the and the unauthorized page is swapped with the index page with an empty context (since they both share the same parent tree).
Now, apparently all routes are created with no context (here) and get their context from here, however the newly matched route (Index, where the user is being redirected) doesn't reach that code block and consistently halts after executing https://github.com/TanStack/router/blob/main/packages/react-router/src/router.ts#L1563.
It looks like the flow just gets interrupted after the beforeLoad is executed, with the Router then failing here as no context can be provided to the loader for the last route matched (because it never gets to merge the context with the matched route).
I'll try making a repro again, but in the meanwhile I hope this can help pinpoint the issue somehow 🤷♂️
@SeanCassiere By any change, do you know when will this be fixed approximately? It really makes a lot of problems in my app and, unfortunately, I cannot rollback to previous version, because there are other bugs there. Thank you a lot for your work
I don't have the bandwidth to look into this until probably mid next week.
@tannerlinsley any idea around where this bug would be happening?
In the meantime here is a workaround
export const Route = createFileRoute('/a-route/')({
component: () => {
const navigate = useNavigate();
setTimeout(() => {
navigate({ to: '/another-route' });
}, 0);
return null;
}
})
ugly but working on my side
In the meantime here is a workaround
export const Route = createFileRoute('/a-route/')({ component: () => { const navigate = useNavigate(); setTimeout(() => { navigate({ to: '/another-route' }); }, 0); return null; } })
ugly but working on my side
Thank you very much, I will try it
I tested replacing throw redirect({}) with router.navigate() and now issue does not appear. So, issue appear only with throw redirect(). I event don't need setTimeout, it works without it( I do it in beforeLoad, not in component, so hook is not available )
I tested replacing throw redirect({}) with router.navigate() and now issue does not appear. So, issue appear only with throw redirect(). I event don't need setTimeout, it works without it( I do it in beforeLoad, not in component, so hook is not available )
This also worked for me, and I'm on v1.32.2
Yup, this workaround does the job :+1:
One thing to be careful of is to include { replace: true }
in the options to navigate
, otherwise it will put the route onto the stack and probably break the back button.
I can confirm I am running into the same issue and the culprit seems to be throw redirect()
.
My reproduction: https://stackblitz.com/edit/github-xhruej?file=src%2Froutes%2Fabout.tsx,src%2Froutes%2Findex.tsx&file=src%2Froutes%2Fabout.tsx
Steps to Reproduce the Bug or Issue
- Open the DevTools console.
- Notice you are on the About page. If you look in the console, you were redirected on initial load.
- Press the "Navigate" button.
- Notice you are on the Index page. If you look in the console, you will see that the loader context is
undefined
.
Expected behavior
- Open the DevTools console.
- Notice you are on the About page. If you look in the console, you were redirected on initial load.
- Press the "Navigate" button.
- Notice you are on the Index page. If you look in the console, the loader context is an object containing the
queryClient
After navigating to a page that has been redirected from, the loader context should not be undefined. We are suggested by the docs / examples to use loader: ({ context: { queryClient }) => {}
when defining loaders, which is not valid if context can be undefined.
I can confirm I am running into the same issue and the culprit seems to be
throw redirect()
.My reproduction: https://stackblitz.com/edit/github-xhruej?file=src%2Froutes%2Fabout.tsx,src%2Froutes%2Findex.tsx&file=src%2Froutes%2Fabout.tsx
I didn't have time to make a reproduction but this is exactly what I said I'm facing in https://github.com/TanStack/router/issues/1531#issuecomment-2096533191.
An error is thrown here on the offending route (in this case, /
),and then the cached match in the router store gets updated (here). However, the route remains in a pending state because the finally statement overrides this by using the scoped match
object. On the next iteration, it is then skipped as it's marked with isFetching: true
.
Moving the updateMatch
call from the finally block to the end of the try block fixes this context issue for me, and so does reverting this commit which was introduced in 1.28.6.
cc @SeanCassiere I don't know what that commit was supposed to fix, so I haven't made a PR reverting it but I'm happy to if needed 👍
Moving the
updateMatch
call from the finally block to the end of the try block fixes this context issue for me...
@freshgiammi this seems to do the trick.