Home > database >  React state change from within button's click handler is preventing form submission
React state change from within button's click handler is preventing form submission

Time:12-11

Consider the code below:

function Item({name, _key})
{
   console.log('rendering Item')
   const [updatingName, setUpdatingName] = useState(false);
   const nameInputElement = useRef();

   useEffect(() => {
      if (updatingName) {
         nameInputElement.current.focus();
      }
   }, [updatingName]);

   function onUpdateClick() {
      setUpdatingName(true);
   }

   function onCancelClick() {
      setUpdatingName(false);
   }

   return (
      <div>
         <input ref={nameInputElement} type="text" defaultValue={name} name="name"
         disabled={!updatingName} />

         {!updatingName
         ? <>
            <button key={1} type="button" onClick={onUpdateClick}>Update</button>
            <button key={2} type="submit" name="delete" value={_key}>Remove</button>
         </>
         : <>
            <button key={3} type="submit" name="update" onClick={(e) => {setUpdatingName(false)}}>Save</button>
            <button key={4} type="button" onClick={onCancelClick}>Cancel</button>
         </>}
      </div>
   )
}

function ItemList({title})
{
   return <>
      <h1>{title}</h1>
      <form method="post" onSubmit={(e) => {console.log('submitting');e.preventDefault()}}>
         <Item name={'small'} _key={0} />
      </form>
   </>
}

export default ItemList;

The problem that I am facing is the click of the Save button. When it's clicked, as you can see, I trigger a state change. But at the same time, I also want the button to cause the underlying <form>'s submission.

(To check whether the form is submitted, I've prevented its default submit mechanism and instead gone with a simple log.)

However, it seems to be the case that when the state change is performed from within the onClick handler of the Save button, it ceases to submit the form. If I remove the state change from within the handler, it then does submit the form.

Why is this happening?

Edit angry-fast-upe615

You could also use useTransition hook, to tell React to update the state after the underline logic (submitting the form) has already happened:

function Item({ name, _key }) {
  console.log("rendering Item");
  const [isPending, startTransition] = useTransition();
  const [updatingName, setUpdatingName] = useState(false);
  const nameInputElement = useRef();

  useEffect(() => {
    if (updatingName) {
      nameInputElement.current.focus();
    }
  }, [updatingName]);

  function onUpdateClick() {
    setUpdatingName(true);
  }

  function onCancelClick() {
    setUpdatingName(false);
  }

  return (
    <div>
      <input
        ref={nameInputElement}
        type="text"
        defaultValue={name}
        name="name"
        disabled={!updatingName}
      />

      {!updatingName ? (
        <>
          <button key={1} type="button" onClick={onUpdateClick}>
            Update
          </button>
          <button key={2} type="submit" name="delete" value={_key}>
            Remove
          </button>
        </>
      ) : (
        <>
          <button
            key={3}
            type="submit"
            name="update"
            onClick={(e) => {
              startTransition(() => setUpdatingName(false));
            }}
          >
            Save
          </button>
          <button key={4} type="button" onClick={onCancelClick}>
            Cancel
          </button>
        </>
      )}
    </div>
  );
}

Edit angry-fast-upe615

  • Related