-
-
Notifications
You must be signed in to change notification settings - Fork 617
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
Problems with derived atom which has a promise as its initial value #1114
Comments
It seems like this pull request fix(core): handle returning infinite promise in derived atoms #1089 created another issue. IssueA loadable atom of a derived atom trigger infinite loop under the following conditions.
ReproductionA third click within 5 seconds of the second click will trigger infinite loop. https://codesandbox.io/s/jovial-firefly-bhb2s2?file=/src/App.tsx How this happenThe infinite loop is occurred in
|
Too bad we didn't have a test for it. I felt a little too naive when I did #1089. I haven't followed all of your comments, but seems like you can help the project, by creating failing test cases and even open a PR to fix them. |
I created a pull request (#1118) to revert #1089 to solve infinite loop. I also added a test for a infinite loop in this loadable case. I don't think this test is comprehensive enough, but we need to fix this infinite loop for now. "Not comprehensive enough" means that
|
I will take a look later. Do you mean we can't fix #1054? Or, do you have any other idea to fix? |
So far, I can't think of a solution that doesn't have problems. If we update
But this change might cause a problem as I mentioned in the last part of the first comment. I'm not 100% sure so I want to ask for yor insight. |
I am glad you agree. And yes, I understand that this is a tricky bug. I also understand that the pattern in #1054 is useful. Here is a workaround to use a derived atom, which has https://codesandbox.io/s/drived-async-atom-workaround-gpsi4d?file=/src/App.js I'm excited to use Jotai for my next project! Thank you very much for this wonderful work. |
I played around with the codesandbox in this issue #1054 (comment) to understand the behavior when the atom has
Promise
as its initial value.Then, I have noticed that this pull request #1089 does not solve the problem in many cases, and that even in cases where it appears to solve the problem, there is a another problem.
Cases where the problem is not resolved
This is just one atom added to the first codesandbox. Now the
atomWithSuspense
no longer works.https://codesandbox.io/s/vigorous-roman-45dbx5?file=/src/App.js
After digging deeper into the issue, I realized that this behavior was the expected behavior.
Why this codesandbox is the expected behavior
The reason why
atomWithSuspense
does not work when the initial value is a infinitePromise
is because it is not registered in theDependents
ofnullableAtom
.Normally, a derived atom is registered in
Dependents
of dependencies atstore[SUBSCRIBE_ATOM]
inuseAtomValue
, but if initial value is aPromise
, it is not executed becausethrow Promise
occurs before that. So,atomWithSuspense
will not registered in theDependents
ofnullableAtom
and will not work.Why does the first codesandbox still work
Basically, the only chance for a derived atom to be registered in dependencies'
Dependents
is when it is mounted for the first time. However, there is one more place where this can happen. That isflushPending
.Inside
flushPending
, atoms registered in thependingMap
are registered in dependencies'Dependents
under certain conditions. Note that atoms that are not mounted are also registered in thependingMap
. Atoms are registered in thependingMap
when they are first obtained, soatomWithSuspense
, which is not mounted, is also registered in thependingMap
.The conditions under which atoms are registered as
Dependents
are below:For this to work,
nullableAtom
must be mounted before the firstflushPending
, as in the first codesandbox. In other words,nullableAtom
must be the first atom to be mounted.What is a another problem in cases where it works
In the first codesandbox,
atomWithSuspense
was registered inDependents
ofnullableAtom
as stated above. However, ifSuspenseViewer
is detached without ever clicking the "Fetch new value" button,atomWithSuspense
is not unmounted because it was not mounted, and it is not removed from theDependents
ofnullableAtom
. Therefore,atomWithSuspense
continue to be retained even if it is no longer referenced by anyone. This problem occurs even if the initial value is not an infinite promise.The text was updated successfully, but these errors were encountered: