react icon indicating copy to clipboard operation
react copied to clipboard

[React 19] Controlled checkboxes are reset by form submission and form.reset()

Open jeremy-deutsch opened this issue 1 year ago • 15 comments

Summary

After a form is submitted with an action, if one of the form's fields is a checkbox or radio input controlled by its checked prop, that element is reset as if it were uncontrolled. The same happens when the reset() method is called on the form. (Expected behavior: those fields are not reset.)

import { useState } from "react"

export default function Page() {
  const [isChecked, setIsChecked] = useState(false);

  return (
    <form action={() => {
      console.log("hello world!");
    }}>
      <label>
        Some checkbox
        <input type="checkbox"
          checked={isChecked}
          onChange={(e) => {
            setIsChecked(e.target.checked);
          }}
        />
      </label>
      <button>Submit form</button>
    </form>
  );
}

Repro: https://codesandbox.io/p/sandbox/checkbox-reset-repro-sff3sr

Related: https://github.com/facebook/react/issues/30580, https://github.com/reactjs/react.dev/pull/7340

jeremy-deutsch avatar Dec 07 '24 19:12 jeremy-deutsch

I'm seeing the same issue using latest Next15 version.

Code sandbox: https://codesandbox.io/p/devbox/cocky-shannon-forked-8qlwzy?file=%2Fapp%2Fform%2Fcomponent.tsx%3A11%2C15&workspaceId=ws_YJunuyU6avBk8pMTbNjaGv

ray-marr-ho avatar Dec 17 '24 15:12 ray-marr-ho

@eps1lon is there any chance this issue (as well as #30580) could be given the normal bug tags ("status:unconfirmed" or "type:bug"), since it's a bug in stable React?

I'm worried that this issue (as well as many others) isn't being triaged because the "React 19" issue tag was supposed to refer to the React 19 beta, even though it's mostly now being used to tag problems with stable React.

jeremy-deutsch avatar Feb 13 '25 15:02 jeremy-deutsch

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

github-actions[bot] avatar Jun 07 '25 13:06 github-actions[bot]

This is still an issue! We've needed to remember to manually reset controlled inputs when we use the form action system.

jrenjilian avatar Jun 09 '25 12:06 jrenjilian

bump!

AleTopp avatar Jun 30 '25 09:06 AleTopp

I am seeing the same issue : https://github.com/ortin779/react-form-actions-reset

ortin779 avatar Jul 03 '25 19:07 ortin779

I've spent three days trying to understand what I was doing wrong, but turns out it was a React bug affecting very essential functionality, and it's over a year old!

kirilledelman avatar Jul 18 '25 16:07 kirilledelman

Just ran into this issue. I did not expect this to be a bug with React, but here we are.

My current workaround is to create my own checkbox component that uses a button and a hidden input. The boolean is just cast a string for the value of the hidden input. This does mean your form data will pass as a string, but that happens already normally with checkboxes as they get passed as "on" typically.

LeonBlade avatar Jul 23 '25 20:07 LeonBlade

@LeonBlade My workaround was to simply add a completely redundant setRememberMe(rememberMe) at the end of the useEffect that interpreted formState after the server call returned. You don't have to send the actual value to the server. Apparently then it behaves like other controlled fields.

kirilledelman avatar Jul 24 '25 00:07 kirilledelman

@kirilledelman It's a simple solution. I don't think I'll be using it though because it means having to add this logic to any form that might use checkboxes. That's why I opted to modify my component instead. Hopefully this can be addressed at some point.

LeonBlade avatar Jul 24 '25 07:07 LeonBlade

Bumping this since it's still very much an issue, which is pretty insane.

johnloven avatar Aug 14 '25 14:08 johnloven

This is working for me, instead of

<form action={formAction}>

Add a startTransition and call the formAction inside of that

    <form
      onSubmit={(event) => {
        event.preventDefault();
        const form = event.currentTarget;
        startTransition(() => {
          formAction(new FormData(form));
        });
      }}
    >

notflip avatar Aug 28 '25 20:08 notflip

This is working for me, instead of

<form action={formAction}>

Add a startTransition and call the formAction inside of that

    <form
      onSubmit={(event) => {
        event.preventDefault();
        const form = event.currentTarget;
        startTransition(() => {
          formAction(new FormData(form));
        });
      }}
    >

This is working for me. Thank you so much! Could you please explain us how that works?

danielkochengineer avatar Sep 01 '25 09:09 danielkochengineer

This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

github-actions[bot] avatar Dec 03 '25 15:12 github-actions[bot]

Bump. This will supposedly be worked on soon (https://github.com/facebook/react/pull/35168#issuecomment-3551557781)

jeremy-deutsch avatar Dec 04 '25 16:12 jeremy-deutsch