Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upBug: startTransition suspends immediately in odd circumstances #17911
Comments
This comment has been minimized.
This comment has been minimized.
|
Just FYI same behavior on the |
This comment has been minimized.
This comment has been minimized.
|
Can you create a reduced one-file example with no libraries? |
This comment has been minimized.
This comment has been minimized.
|
I can try to find some more time to put into this but no promises. I have to believe there’s something going wrong in how my useQuery hook is sharing the updateState function with the queryManager. I’m most interested in hearing if that’s violating any React constraints which might be causing this. |
This comment has been minimized.
This comment has been minimized.
|
@gaearon - I managed to get this reproduced! :D https://codesandbox.io/s/priceless-shirley-o6sfg If you click pretty much any of the buttons, you'll often see things suspend. Note the call to Sorry for all the extra crap in the sandbox - I chased down a ton of false leads here, and honestly don't have the time to clean it all up—I need to get back to work! :) But I'm stoked to finally be able to give you something hopefully actionable. Lastly, I do realize the layoutEffect isn't even needed, in this particular case, or probably in my original code which surfaced this odd behavior. But it does seem like a bug, unless I'm missing something. |
This comment has been minimized.
This comment has been minimized.
|
Also - h/t to Daishi Kato for helping to get this sandbox started :D |
This comment has been minimized.
This comment has been minimized.
|
So, the layout effect runs when a child component throws a promise. Is it a bug or a behavior. (Note, my first comment in the twitter thread was pointless.) |
React version: 0.0.0-experimental-f42431abe
Please note that I do realize my repro steps are poor at best. I'm not filing this issue in hopes of support; I'm only filing this issue to provide one more datum point to help diagnose what I believe to be a bug, which I'm assuming you'll see more reports of.
Steps To Reproduce
tl;dr - there are some circumstances when a thrown promise inside a hook causes an immediate suspense, instead of respecting the startTransition it's inside of.
startTransition for me is always, in this case, called outside of the normal React handlers. In this case history.listen
https://github.com/arackaf/booklist/blob/special/suspense-blog/react/modules/books/booksSearchState.ts#L75
This is my Suspense-enabled hook that's called as a result of the state update inside the code above
https://github.com/arackaf/micro-graphql-react/blob/feature/suspense/src/useQuery.js#L22
the Promise throwing happens here
https://github.com/arackaf/micro-graphql-react/blob/feature/suspense/src/queryManager.js#L116
Here's the specific chain of events that leads to the breakage.
Things work so long as there's always been an existing promise, for the queryManager to throw, ie line 116 in the code immediately above. But the minute there's cached results, and the queryManager invoke's the hook's setState method (which it passed it), ie line 120 here
https://github.com/arackaf/micro-graphql-react/blob/feature/suspense/src/queryManager.js#L120
then all future suspenses immediately start suspending, and I always get my fallback, always.
The setState method is shared between the hook, and queryManager here
https://github.com/arackaf/micro-graphql-react/blob/feature/suspense/src/useQuery.js#L17
I stress that I do not need support, here; this is just a side project, an unimportant one, and this whole branch is only for Suspense experimenting. But something does definitely appear to be wrong, and I'm hoping this report can help you guys find it.
The current behavior
startTransition only works until the hook's setState is called from the queryManager it creates, at which point startTransition always triggers hard suspenses, showing my fallback.
The expected behavior
startTransition should never trigger the fallback until the timeout has expired.