Uh oh!
There was an error while loading. Please reload this page.
Fix form status reset when component state is updated - #34075
Conversation
Comparing: eb89912...aa288b5 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: (No significant changes) |
| // This is intentionally set here instead of pushHostContext because | ||
| // pushHostContext gets called before we process the state hook, to avoid | ||
| // a state mismatch in the event that something suspends. |
There was a problem hiding this comment.
I'm not sure I fully understand this comment. If something suspends we pop back up. And the Component we're rendering (here: TransitionAwareHostComponent) should not be able to read the current Context just yet which is what pushing the context before the render would do, right? We can't nest Host Context anyway though. So this seems safe to move the push after the render.
There was a problem hiding this comment.
A common issue is that CompleteWork and UnwindWork unconditionally calls popHostContext. That's called even when something in the component suspends because it doesn't know if we suspended before or after the push. There's no state to indicate that.
That's why we always pushHostContext and other push things immediately when we enter the update before anything could error or suspend.
Since renderTransitionAwareHostComponentWithHooks might suspend, I don't think it's safe to move the pushHostContext after it. In fact I'm surprised we don't have a test that fails for that case. Maybe we're lacking coverage or there's some other thing that covers it but it shouldn't be safe in general.
There was a problem hiding this comment.
Makes sense. Moved the pushContext back to its original place. When the state changes, we update the context value which works because only a single transition provider is allowed.
Basically, we set the value on pushHostContext and when we update state.
There was a problem hiding this comment.
Can you revert this comment back to the original now too please?
b6348c2 to
77dc8ccCompare77dc8cc to
9be8342Comparea8e8216 to
692d5d9Compareredbmk
commented
Aug 27, 2025
Would love to see this merged in soon. We're blocked from upgrading to Next 15 and React 19 until this issue is fixed - will also have to wait for Next to pull in a new canary release after this is merged. @sebmarkbage any chance you could review the most recent changes? |
692d5d9 to
aa288b5CompareUh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Vordgi <sasha2822222@gmail.com> DiffTrain build for [8ac5f4e](react@8ac5f4e)
Co-authored-by: Vordgi <sasha2822222@gmail.com> DiffTrain build for [8ac5f4e](react@8ac5f4e)
devongovett
commented
Apr 15, 2026
Is there a release planned that might include this fix? This is still an issue in the latest stable version. |
redbmk
commented
Apr 18, 2026
@devongovett it looks like it's fixed in 19.2 Screen.Recording.2026-04-17.at.5.39.21.PM.movCompare that with the behavior here: #31363 (comment) how are you recreating it? |
I'm still noticing this issue on 19.2.5: typeButtonProps=DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>,HTMLButtonElement>functionSubmitButton(props: PropsWithChildren<ButtonProps>): React.JSX.Element{const{pending}=useFormStatus()const[debouncedPending,setDebouncedPending]=useState(false)useEffect(()=>{if(pending){consthandler=setTimeout(()=>{setDebouncedPending(true)},400)return()=>{clearTimeout(handler)setDebouncedPending(false)}}else{setDebouncedPending(false)}},[pending])console.log({pending, debouncedPending});return<Button{...props}type="submit">{props.children}{pending&&debouncedPending&&<Spinner/>}</Button>}Without the effect the |
redbmk
commented
Apr 23, 2026
OK I was wrong... the react.dev site SAYS 19.2, but the site itself is actually using a canary build of 19.3. The problem is React rarely pushes new stable builds and when they do it's usually for major security bugs. 19.2.0 was published back in October and there have only been 13 commits between then and 19.2.5 which was just released a couple weeks ago. Meanwhile, there have been 492 commits between 19.2.0 and the latest commit in main, including this PR. React seems to want you to use frameworks like nextjs that depend on canary builds rather than using stable versions. Compare these stackblitz's for example: Screen.Recording.2026-04-23.at.9.24.47.AM.movSo, it is fixed, but it won't be release until 19.3.0 comes out, which could be... who knows when. If you're OK with rolling a canary version you could use the latest. If you're not using NextJS you could at least use the version their latest version is pinned to in hopes that they've done enough vetting to say that version is stable enough for them. |
RomkeSandwave
commented
Apr 24, 2026
Thanks for finding out for us! |
Alternate to #33351 without the regression highlighted in #33351 (comment)
Host context is now updated in
pushHostContext(similar to normal React Context) in addition to duringupdateHostComponent.Closes#30368
Closes#33351