-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(useStorageValue): Allow setting of state even if the component has not mounted #959
Conversation
Codecov Report
@@ Coverage Diff @@
## master #959 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 60 60
Lines 1060 1059 -1
Branches 184 184
=========================================
- Hits 1060 1059 -1
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
Maybe what happens is something like this (referring to the components in my codesandbox):
Just a quick thought. Ps. that codecov/patch action certainly seems to take its time 😄 |
Well, okay, the reason - i've finally got it =) What we know about strict mode - effects are triggered twice, |
Oh, nice! I should have thought about |
But what should be done about this? This bug is very distracting, even if it only exists in |
I'm trying to make a solution at the moment, but i see literally no chance of making |
Ofc we can go with solution you proposed, but it is only fix of single symptom, not its source. |
Well, this relates to another thing I had in mind earlier today. Why are we using According to the React team it is an anti-pattern to check whether the component is mounted or not before setting state. They argue that any state setting functions should be cancelled before the component unmounts instead. They go more detail into this in the blog post. This article talks about the same topic, but is a bit more fresh. |
To expand on my previous comment: From the perspective of a hook library, it essentially should be the user of the stateful hook's responsibility to check that the state is not set after the component has unmounted, not the library's. |
Mostly |
Indeed. And the articles I linked both argue that in such situations, it would be correct to cancel the state settings functions (maybe an async event handler or a As pointed in the second of the articles I referenced, The React team also makes a good point here:
|
it is impossible to cancel async chain midair, in case processing went further direct handlers - you're stuck Promise.
then(()=>{
Promise2ThatTakesLotsOfTime().then(setState) // this one already went async
// unmount happens here
}) As for now there is an AbortToken, but its not so widely common |
And to respond in the context of this library, |
Isn't this possible using the From the second article useEffect(() => {
const abortController = new AbortController() // creating an AbortController
fetch(url, { signal: abortController.signal }) // passing the signal to the query
.then(data => {
setState(data) // if everything went well, set the state
})
.catch(error => {
if (error.name === 'AbortError') return // if the query has been aborted, do nothing
throw error
})
return () => {
abortController.abort() // stop the query by aborting on the AbortController on unmount
}
}, []) In any case, in the article the React team seems to suggest that such state setting functions should be made cancellable. |
TBC im sitting with a thought of dropping lots of |
I'm glad to hear that! Let me know, if I can help in refactoring away the |
As said - yes, abort controller kinda solves situation, but it is not widely supported.
|
Also, using |
welp, everything ended up with complete |
That is probably good, the code felt quite difficult before 😄 I got kind of inspired by our conversation here. What do you think about this:
|
Also, I noticed that you used this PR's solution for the bug as part of #960 . Do you mind adding the hacktoberfest-accepted label to this PR? |
There should be another label for that? i thought just hascktoberfest would be fine |
@ArttuOll, are you planning to continue work on react-hookz or is it just hacktoberfest related? |
Yeah, if this PR is not merged, but the code is accepted, that's how they know to count this to my score.
Yes, so no worries that I would just drop everything that I'm working on when this month ends 😁 perhaps not as actively |
@ArttuOll what do you think joining team and becoming maintainer? |
Well, I'm pretty sure I would be able to find time for that and that would surely be interesting, so count me in! |
🎉 This issue has been resolved in version 17.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
What is the current behavior, and the steps to reproduce the issue?
The current behavior has been described in #451. In short, using the
setValue
function provided byuseSessionStorageValue
anduseLocalStorageValue
on first mount could cause other instances of those hooks to get out of sync.What is the expected behavior?
Every instance of the
useSessionStorageValue
anduseLocalStorageValue
hooks should return the same value at all times.How does this PR fix the problem?
By using
useState
to store the value of the tracked key instead ofuseSafeState
.In the sandbox below, I have modified the
useSessionValue
hook in the above way. The example is the one provided in #451 , but this time the reported issue is not present.Why does this work, you might ask? I do not know. I will have to digest this a bit more.
I arrived at this solution from the simple notion that the
state
variable is what gets out of sync. I then started going through everything that affectedstate
. I went through many things, but finally I noticed thatuseSafeState
also "affects"state
(in a sense that it is not the standarduseState
that I picture in my mind when I think about React state). I then tried switching it toa traditional
useState
, which seemed to solve the issue.Checklist