T
TanStack•12mo ago
genetic-orange

react context provider is not updating router context

I have an auth provider wrapping my route provider. I am then using an auth hook and passing its state to the RouteProvider context. When auth state is changed the context does not seem to update. Is this expected behavior?
No description
30 Replies
dependent-tan
dependent-tan•12mo ago
I have to re-read this how do you define "does not update"? can you please provide a complete minimal example by forking one of the existing examples on stackblitz?
genetic-orange
genetic-orangeOP•12mo ago
__root beforeload we ping our server to verify a user session then return the user. If a valid user is present we setUser(user) which should cause a re-render of the <AuthProvider />. Within <InnerApp /> we have a hook useAuth which returns the state of the <AuthProvider /> we then pass this state to the router context. I can see my updated state on a page when using useAuth() but this state change is not reflected within the router context. I'll work on a minimal example
genetic-orange
genetic-orangeOP•12mo ago
No description
dependent-tan
dependent-tan•12mo ago
but this state change is not reflected within the router context.
in which way? how do you monitor the router context? or put differently, which action / result etc would you expect from router?
genetic-orange
genetic-orangeOP•12mo ago
For instance beforeload we validated the user session. Through the context I pass a setUser(user) which updates the user state in the auth provider. Now on the page for testing purposes I use both the useAuth() hook and the Route.useRouterContext() which both pass the same AuthContext. The useAuth() returns the user that was set in the beforeload but Route.useRouterContext() returns only the initial values which is a null user.
genetic-orange
genetic-orangeOP•12mo ago
AuthContext shape below:
No description
dependent-tan
dependent-tan•12mo ago
try calling router.invalidate() after the user is updated
genetic-orange
genetic-orangeOP•12mo ago
I tried this a few times was able to get this to work.
No description
dependent-tan
dependent-tan•12mo ago
hm yeah I saw this workaround a few times I need to ask @Sean Cassiere again what needs to be done here to avoid the sleep
genetic-orange
genetic-orangeOP•12mo ago
This may be better
No description
dependent-tan
dependent-tan•12mo ago
hm the effect does the same thing, it makes the router invalidation being executed in the next microtick, so after the state was processed the problem here is that react's state is not being processed synchronously so you need do delay the router invalidation
genetic-orange
genetic-orangeOP•12mo ago
Yeah looks like I need the sleep wonder if there is a more proper way to go about this
dependent-tan
dependent-tan•12mo ago
the effect looks cleaner TBH 😄 but I guess there is no way around something like this, you need to "await" the state being processed through react and only then invalidate the router
genetic-orange
genetic-orangeOP•12mo ago
I had to do this I thought the useEffect without the sleep was ok but it doesnt work
No description
dependent-tan
dependent-tan•12mo ago
so inside the useEffect, the user was still null?
genetic-orange
genetic-orangeOP•12mo ago
without the sleep if I console.log(user) I see the user info but router.invalidate() would not work and update the context. With the sleep it does update properly Hmm I been loving the router but I think maybe for auth I meet lean into using zustand I thought the router context would be a cool place to do auth but updating the context is bit hacky for me at the moment and see some behaviors such as content showing before the invalidate because of the sleep. hmm wonder what would happen if I pass a zustand store to the router context 🤔
dependent-tan
dependent-tan•12mo ago
depends on whether it updates synchronously?
genetic-orange
genetic-orangeOP•12mo ago
@Manuel Schiller This is what I landed on...
No description
No description
genetic-orange
genetic-orangeOP•12mo ago
No description
dependent-tan
dependent-tan•12mo ago
so with zustand it works?
genetic-orange
genetic-orangeOP•12mo ago
Yeah a pass a store to the context and it works more intuitively atleast for managing global auth
dependent-tan
dependent-tan•12mo ago
good to know
genetic-orange
genetic-orangeOP•12mo ago
Something I just noticed is that the store wrapped with a useStore(). Within the beforeloads/loaders if I for example auth.setUser(validUser) on line 1 and check auth.user on line 2 it will show the old value. I think I will take this a step further to create getters and setters and use the store directly within beforeload and loaders so I can have a syntax like auth.user = validUser and auth.user to get the user
genetic-orange
genetic-orangeOP•12mo ago
This is what I settled on. For having a reactive context value for auth atleast.
No description
No description
No description
correct-apricot
correct-apricot•11mo ago
I wonder if leveraging flushSync would help here for these crucial flows? Since it would ensure that React state is updated before calling router.invalidate()
stormy-gold
stormy-gold•11mo ago
I've used context for my authentication, but would love to get some examples of how to do it properly, I know the example shown uses a await(300ms) in the docs, but wondering what is a more robust solution
harsh-harlequin
harsh-harlequin•10mo ago
I'm also wondering that, any new insight for what a robust solution is ? I'll keep using the await sleep/delay func to sync the state for the moment :/
ratty-blush
ratty-blush•9mo ago
@Gordazo have you managed to find a different solution? or is the sleep 300ms still the thing
harsh-harlequin
harsh-harlequin•9mo ago
Hello! I'm still using a delay func " await delay(0); " before the invalidate
ratty-blush
ratty-blush•9mo ago
await sleep(0) works thank you!

Did you find this page helpful?