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?

30 Replies
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-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-orangeOP•12mo ago

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-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-orangeOP•12mo ago
AuthContext shape below:

dependent-tan•12mo ago
try calling
router.invalidate()
after the user is updatedgenetic-orangeOP•12mo ago
I tried this a few times was able to get this to work.

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-orangeOP•12mo ago
This may be better

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-orangeOP•12mo ago
Yeah looks like I need the sleep wonder if there is a more proper way to go about this
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-orangeOP•12mo ago
I had to do this I thought the useEffect without the sleep was ok but it doesnt work

dependent-tan•12mo ago
so inside the useEffect, the user was still null?
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•12mo ago
depends on whether it updates synchronously?
genetic-orangeOP•12mo ago
@Manuel Schiller
This is what I landed on...


genetic-orangeOP•12mo ago

dependent-tan•12mo ago
so with zustand it works?
genetic-orangeOP•12mo ago
Yeah a pass a store to the context and it works more intuitively
atleast for managing global auth
dependent-tan•12mo ago
good to know
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-orangeOP•12mo ago
This is what I settled on. For having a reactive context value for auth atleast.



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•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•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•9mo ago
@Gordazo have you managed to find a different solution?
or is the sleep 300ms still the thing
harsh-harlequin•9mo ago
Hello! I'm still using a delay func " await delay(0); " before the invalidate
ratty-blush•9mo ago
await sleep(0) works
thank you!