help refactoring context with useEffect into layout `beforeload`?
I'm trying to integreate openauth into a router project, and have been at this on and off for a week or so now. i've come up with a solution, but it's suboptimal and involves setting/getting jotai stores outside of react which seems to be generally discouraged.
basically there's this example i'm trying to roughly port. some of the things tripping me up, but here's my thought process, and would be deeply grateful to any willing to give some thoughts
- there's a bunch of logic happening in a useEffect w/ no deps. this tells me that I would prefer to just pull this logic into a
beforeload
. i'll pull into __root
because, for now, i want auth data accessible at all my pages.
- ok, i pull the logic out, but now i need to set some values which, in the example, are state values. i'm not in a component anymore so i need a solution here -> use context to communicate btwn route loader and context
- i wrap my whole tree in an auth context
- the beforeload is at my _root, so now it's higher in the tree than everything else. this means that the auth context provider renders beneath it. seems like this defeats the solution of pulling it into context. not to mention that
this is sort of where my brain starts go a million different ways and i don't have a good model of how to solve this. i'm just wondering, is there a pattern for doing this type of thing? i'm sorry if this is vague and confusing, i'm just looking for any thoughts on how someone would go about this. my current solution is really not something i'd like to use, so looking for the "proper" way to handle this.33 Replies
stormy-goldā¢7mo ago
can you please share your actual code that you ended up with?
even if its not working
or just pseudocode
right now its just a lot of text š
mute-goldOPā¢7mo ago
sure, 1 sec, i'll have to step back a couple steps
yea my bad, 1min
__root.tsx
so this works now. i'm basically skipping out on context, and anywhere i need to access any of the relevant data, i can just import the atoms and
useAtom(accessTokenAtom)
for example, and it's populated. but i'd prefer to not opt by using stores like i am here, and pass around basically shared values (be it state or jotai atoms, i just used this because they have nice built in local storage persistence)stormy-goldā¢7mo ago
be aware that
beforeLoad
would run upon each navigation
so you would refresh each time you click a link
which can incur some delaysmute-goldOPā¢7mo ago
I did notice that- would you recommend putting an auth initialization somewhere other than beforeLoad then?
stormy-goldā¢7mo ago
either outside of beforeLoad or you cache it somehow so you have a cheap way to skip over it in beforeLoad
mute-goldOPā¢7mo ago
what would be the router equivalent of a useEffect inside of a context provider that mounts at the root of the app?
my goal is to port this example but make use of what ts router provides
and everything i've seen re: react is, avoid useEffect at all costs
stormy-goldā¢7mo ago
it needs to be async, right?
mute-goldOPā¢7mo ago
yea
are you going to say query
stormy-goldā¢7mo ago
ha
š
no
mute-goldOPā¢7mo ago
have had that in the back of my head this whole time lol
stormy-goldā¢7mo ago
i mean you can use it for caching here
but maybe read this thread https://discord.com/channels/719702312431386674/1339690743580721152/1340006793874636914
you are not affected by serialization issues since you are just using router, not start. right?
mute-goldOPā¢7mo ago
correct
what i don't get is, is there not an established pattern for doing this in router?
like this feels like a very common use case
stormy-goldā¢7mo ago
it really depends what you have. sometimes you need to use some providers given to you by a library
how did your solution look like before?
with useEffect etc
mute-goldOPā¢7mo ago
it's this from openauth's examples https://github.com/openauthjs/openauth/blob/master/examples/client/react/src/AuthContext.tsx
GitHub
openauth/examples/client/react/src/AuthContext.tsx at master Ā· open...
⦠Universal, standards-based auth provider. Contribute to openauthjs/openauth development by creating an account on GitHub.
mute-goldOPā¢7mo ago
pretty simple
just do everything i did but in a useeffect, pass down the requisite data as values on the provider
then i turned it into this beforeload, jotai stores with local storage disaster that i now have on my hands
stormy-goldā¢7mo ago
and what triggered the useEffect?
mute-goldOPā¢7mo ago
in this example?
stormy-goldā¢7mo ago
yeah
mute-goldOPā¢7mo ago
it renders providers at the root i believe so runs when the app mounts
stormy-goldā¢7mo ago
so this executes just once?
mute-goldOPā¢7mo ago
as far as i can tell. i never set up this exact thing. but the example there is a pretty simple vite react app, so my understanding is it should only run on page load
stormy-goldā¢7mo ago
so this does not sound like a situation where I would "optimize" away the useEffect
mute-goldOPā¢7mo ago
Ok fair enough
I'm back to this thread with another question. I've been battling with this some more, went ahead and didn't move away from useEffect, though I still want to check auth checks in beforeLoad. I had a tough time for a while getting this to work in beforeLoad, and hit a point where it looks like my Router Context is not what I expect. I decided to give it a go by using an early return with the
Navigate
component as an alternative to beforeLoad + redirect, and was able to achieve the goal. It's curious though, because it seems like the two options should behave pretty similarly, but at different stages with respect to the current component's mount cycle. Here's the code
So I'm getting that console log in my beforeLoad, but in the actual component mount, i'm signed in so i never hit the Navigate mount
I can provide more code, just not totally sure which piece are most relevant
(I also wrap my entire app in a check to see if the auth step has finished running. if it hasn't i return null so i don't show any stale state)stormy-goldā¢7mo ago
so what are you saying here? that the router context and the auth hook have different data?
then you probably need to
router.invalidate()
after you updated the authmute-goldOPā¢7mo ago
yea I am doing that
mute-goldOPā¢7mo ago
this is the sequence of events happening

mute-goldOPā¢7mo ago
in the beforeLoad i'm not actually invoking the redirect because that will break the behavior of the in component check
stormy-goldā¢7mo ago
how are you updating the auth object in context?
mute-goldOPā¢7mo ago
this is my useEffect that runs in the context. then i set my atoms, and they get passed down like
'refresh' case in the switch is the relevant one here
stormy-goldā¢7mo ago
and how do you pass it into router context?
mute-goldOPā¢7mo ago
stormy-goldā¢7mo ago
i still fail to see where
auth
is set on router contextmute-goldOPā¢7mo ago
Dang, right. I just reread the docs on auth w/ context and i messed up a bunch
so if i have to render my auth provider above the <Router>, like this https://github.com/TanStack/router/blob/main/examples/react/authenticated-routes/src/main.tsx
does that mean that i can't get access to search params inside the auth provider?