cookies() bug(?)
Answered
Sloth bear posted this in #help-forum
Sloth bearOP
I found that when I need to update a cookie, the new value is passed from the server layout to the useState/useRef as an initial state from props, but its value is not being updated (I'm using router.refresh(), by the way). I'm getting the new cookie, but the old value is being preserved. If I try to pass token props from the server layout (cookie value), the authorization header preserves the old value. However, I can bypass this by manually updating useRef in a useAuth hook.
Answered by nevz
That's why I think the
If you don't tell React to re-run stuff because something has changed then it will not re-run.
So
useRef
solution is fine, React won't make things work unless you tell it to. So the previous videos/issue you shared aren't bugs but how React works.If you don't tell React to re-run stuff because something has changed then it will not re-run.
So
useRef
is a great solution for this because of being able to keep a reference to the object49 Replies
Well your client side is preserved even if you use
To me it seems like you don't even need a ref nor a state since the token is just a string and it comes from the server which is stable
router.refresh
.To me it seems like you don't even need a ref nor a state since the token is just a string and it comes from the server which is stable
Sloth bearOP
No
I found the same issue
I'm getting the new token from the props (server layout), but the value is never getting updated
The problem is that everything works, but even if you initialize a state from a cookie prop — you'll anyway get old value
This is bug
So your second snippet works right where you check if authData.current !== initialData?
Sloth bearOP
Yes, with this hook I'm getting the new value
So my question is do you really need a ref or a state?
Sloth bearOP
Yes, because I need to manually update it
Otherwise I dont get the new value
You mean you manually update it somewhere client side?
Sloth bearOP
in the hook useAuth
Well I don't see any other code in your authState other than replacing the ref. Here's an experiment:
In this component:
In this component:
Sloth bearOP
everything works here
If i pass token from the props - value is not updated
that's the problem
So replacving authState.current to just token does not work?
Sloth bearOP
yes
I'm not the only one with this problem
same issue from the issues
If you are saying that the token from the props is not updated but you get a different token in your
Unless you haven't added the token in your useMemo dependencies array
useAuth
then that doesn't really make sense to me.Unless you haven't added the token in your useMemo dependencies array
Sloth bearOP
Listen, everything works here with useAuth hook.
And I don't need to recreate the urql client
This is anti-pattern
The problem is that props doesn't updates useState, useRef and if I pass the token in headers
That's the problem
Ok just to clarify:
1. You don't want to pass the token in the dependencies array because it will re-run the
2. You use
3. Everything works but you're trying to find if there's a better way instead of doing what you're doing at the moment?
1. You don't want to pass the token in the dependencies array because it will re-run the
useMemo
and re-create the client2. You use
ref
so you don't need to pass it in the deps array3. Everything works but you're trying to find if there's a better way instead of doing what you're doing at the moment?
Sloth bearOP
You don't understand the problem
If I'll pass token manually - I don't get new value
This hook is a workaround to get the new value
And it should work without this hook
useMemo is fine
Well the thing is with
But if you think I still don't understand the problem, please share a reproducible repo just to understand clearly
useMemo
if you pass a value to it that's not in the dependencies array (which I assume you're not doing, but not clear with the screenshot since it's cut), you will not really get an updated value because it will not run because you didn't tell it to run when a value gets updated. And if you do not want this kind of solution I think your solution is already good for your use-case 🤷♂️ The problem is that props doesn't updates useState, useRef and if I pass the token in headersAnd like I said before, even if you use
router.refresh
the initial data that you pass to useState
or useRef
will never get changed because the state is preserved meaning the state is still active even after a router.refresh
But if you think I still don't understand the problem, please share a reproducible repo just to understand clearly
And the video you shared isn't a bug, that's how it works, navigation/router refresh preserves state
Sloth bearOP
It's not about router.refresh
Sloth bearOP
You can console.log token in graphql.ts - you are getting the new value, but if you are passing it - you don't get it
But with useAuth workaround its works
and you don't need to pass the token in the dependency array
to make it work
Well it's using reference that's why it works, it's partly because of closures and mainly because of the object reference, but it does indeed "save" the reference in the callback function of
I think it's a good solution for this use-case, you store information and read it later somewhere. Because the thing to get it work is to really pass the token in the dependencies array but that will re-run the memo which you don't want.
So there isn't really a good solution other than what you have at the moment.
authExchange
and since callback functions can be called on-demand and it has the object reference "saved" authCurrent
when the callback gets executed, it points to the correct value in memory because of itI think it's a good solution for this use-case, you store information and read it later somewhere. Because the thing to get it work is to really pass the token in the dependencies array but that will re-run the memo which you don't want.
So there isn't really a good solution other than what you have at the moment.
Sloth bearOP
I understand it, thanks, but why I just cannot pass it right into the headers?
You can but again you will need to pass the token to the deps array. This is the only way you can make it work, but again this re-creates the client.
Which is again important because it tells the
You can use
useMemo(() => {
// ... other code
}, [token]);
Which is again important because it tells the
useMemo
hook that something has changed, otherwise it will not really run the useMemo
if you keep it empty, it will only run once meaning it will use the old value it took from the closure not the new one. That's the thing with these dependencies array.You can use
useRef
because React knows it's a stable reference that the object itself is the same object reference in memory regardless of re-renders. So it's not required in the deps arraySloth bearOP
It is not allowed actually. You'll get infinte loop and recreating the client is bad.
That's why I think the
If you don't tell React to re-run stuff because something has changed then it will not re-run.
So
useRef
solution is fine, React won't make things work unless you tell it to. So the previous videos/issue you shared aren't bugs but how React works.If you don't tell React to re-run stuff because something has changed then it will not re-run.
So
useRef
is a great solution for this because of being able to keep a reference to the objectAnswer
Sloth bearOP
Ok. Thanks for your time