react reconciliation causes unexpected result

120 views Asked by At

hi I have a question about react reconciliation.

here's my code

const Foo = () => {
   const [buttonId, setButtonId] = useState(1);

   const handleClick = (e: React.MouseEvent) => {

      // when I uncomment below line, submit is blocked.
      // e.preventDefault();

      // when I comment below line, form submission not occurred. 
      // it makes sense because Btn2 Element doesn't exist never anymore 
      setButtonId(2);
   };

   const handleSubmit = () => {
      // when click Btn 1, handleSubmit is called and printed 'submit!'
      console.log('submit!');
   };

   return (
      <form onSubmit={handleSubmit}>
         <input type="text" name="dummy" value="dummy" />

         // Why is the form submitted when I clicked on Btn 1? 
         {buttonId === 1 ? (
           <button type="button" onClick={handleClick}>Btn 1</button>
         ) : (
           <button type="submit">Btn 2</button>
         )}
      </form>
   )
};

When I click button1, form submission is processed even though button1 don't have type="submit".

What's even weirder is that when I uncomment e.preventDefault() in button1 onClick handler and click it, form submission don't happened.

Why is the handler that handling the click event(handleclick) bounded to the first button involved in the submission event of the next button? Is it expected and right result in react reconciliation?

I guess that it is a problem that occurs in the process of updating the type of element during the reconciliation process.

I already know that registering different keys to each button can solve this issue. but I want to know why this happens.

Who's gonna give me a clear thought?

Please check out this link: https://codesandbox.io/s/ecstatic-wozniak-s7r7rq?file=/src/App.js

1

There are 1 answers

2
semperlabs On

Try adding a key to the button element, so React knows that those are different elements

    <form onSubmit={handleSubmit}>
      <input type="text" name="dummy" value="dummy" />

      {buttonId === 1 ? (
        <button key="1" type="button" onClick={handleClick}>
          Btn 1
        </button>
      ) : (
        <button key="2" type="submit">Btn 2</button>
      )}
    </form>