Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Ensure form state is up to date when using uncontrolled components#3790

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
RobinMalfait merged 2 commits intomainfromfix/issue-3760
Sep 12, 2025

Conversation

RobinMalfait
Copy link
Member

@RobinMalfaitRobinMalfait commentedSep 12, 2025
edited
Loading

This PR fixes an issue where uncontrolledSwitch orCheckbox components' form state aren't always up to date when calling theonChange handler.

This is because theonChange handler is called at the same time the internal state is updated. That means that if you submit the nearest form as part of theonChange handler that the form state is not up to date yet.

We fix this by callingflushSync() before we call theonChange handler when dealing with an uncontrolled component.

Test plan

Setup a small reproduction with both a controlled and uncontrolled checkbox

Reproduction
import{Switch}from'@headlessui/react'import{useRef,useState}from'react'import{flushSync}from'react-dom'exportdefaultfunctionApp(){letformRef=useRef<HTMLFormElement>(null)let[enabled,setEnabled]=useState(true)let[submisisons,setSubmissions]=useState<Array<Record<string,string>>>([])return(<div><formclassName="p-8"ref={formRef}onSubmit={(e)=>{e.preventDefault()letform=Object.fromEntries(newFormData(e.currentTarget).entries())asRecord<string,string>setSubmissions((s)=>s.concat([form]))}}><divclassName="flex flex-col gap-1"><divclassName="flex items-center gap-2"><Switchname="my-uncontrolled-switch"className="data-checked:bg-blue-500 aspect-square rounded border bg-white p-2"defaultChecked={true}onChange={()=>{formRef.current?.requestSubmit()}}/><div>Uncontrolled switch</div></div><divclassName="flex items-center gap-2"><Switchname="my-controlled-switch"className="data-checked:bg-blue-500 aspect-square rounded border bg-white p-2"checked={enabled}defaultChecked={true}onChange={(v)=>{// If you are controlling state yourself, then the `form` fields are// based on the incoming value, so in this case you have to call the// flushSync() yourself.flushSync(()=>setEnabled(v))formRef.current?.requestSubmit()}}/><div>Controlled switch</div></div><buttontype="submit"className="mt-4 w-56 border">            Submit</button></div><hrclassName="my-8"/><h3>Form submisisons:</h3><pre>{JSON.stringify(submisisons.toReversed(),null,2)}</pre></form></div>)}

Before:

Notice that the moment I click theuncontrolled checkbox, the form is not up to date yet. Pressing submit again shows the correct value even though visually nothing changed anymore.

Screen.Recording.2025-09-12.at.14.57.01.mov

After:

Here the form state is always up to date when submitting as part of theonChange handler.

Screen.Recording.2025-09-12.at.14.57.34.mov

Fixes:#3760

@vercelVercel
Copy link

vercelbot commentedSep 12, 2025
edited
Loading

The latest updates on your projects. Learn more aboutVercel for GitHub.

ProjectDeploymentPreviewCommentsUpdated (UTC)
headlessui-reactReadyReadyPreviewCommentSep 12, 2025 1:05pm
headlessui-vueReadyReadyPreviewCommentSep 12, 2025 1:05pm

@RobinMalfaitRobinMalfait merged commit987bfa3 intomainSep 12, 2025
8 checks passed
@RobinMalfaitRobinMalfait deleted the fix/issue-3760 branchSeptember 12, 2025 13:12
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@philipp-spiessphilipp-spiessphilipp-spiess approved these changes

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

UncontrolledCheckbox/Switch firesonChange before change

2 participants

@RobinMalfait@philipp-spiess

[8]ページ先頭

©2009-2025 Movatter.jp