Bug: Event handlers are not reconciled as expected when conditionally rendering buttons inside a form

This issue has been created since 2022-11-10.

React version: 18.2.0

Steps To Reproduce

  1. Create a form containing two buttons, one of them with type="submit" and the other with type="button". Conditionally render one or the other based on state that is mutated by the form's onSubmit handler and the type="button" button's onClick handler.
  2. Observe that the button with type="button" incorrectly triggers the form's onSubmit handler.

Link to code example
https://codesandbox.io/s/dreamy-darkness-dodxv5?file=/src/App.js

The current behavior

In the above scenario, the button with type="button" is triggering the parent form's onSubmit handler.

2022-11-10.11-34-42.mp4

The expected behavior

In the above scenario, the button with type="button" should not trigger the parent form's onSubmit handler. Currently, this can be achieved by adding a key prop to one or both buttons:

2022-11-10.11-35-10.mp4
TNick wrote this answer on 2022-11-12

I don't think this has anything to do with React, specifically.

Adding a e.preventDefault(); in the button's onClick handler fixes the issue.

import { useState } from "react";

export default function App() {
  const [someState, setSomeState] = useState(false);
  return (
    <form
      onSubmit={(e) => {
        e.preventDefault(); // don't reload the page
        console.log("onSubmit");
        setSomeState(true);
      }}
    >
      {someState ? (
        <button
          type="button"
          onClick={(e) => {
            e.preventDefault();
            console.log("onClick");
            setSomeState(false);
          }}
        >
          button
        </button>
      ) : (
        <button type="submit">submit</button>
      )}
    </form>
  );
}
vxsl wrote this answer on 2022-11-14

@TNick thanks for your reply. Why would the non-submit button's default action trigger form submission though?

If you remove the conditional rendering, the button does not have this default action:

https://codesandbox.io/s/blue-fog-64h33z?file=/src/App.js

bosiwa1 wrote this answer on 2022-11-19

that look cool

TNick wrote this answer on 2022-11-19

Well, this is not a behavior that I can explain.
Seems that if you pull out the submit button the error is gone.

import { useState } from "react";

export default function App() {
  const [someState, setSomeState] = useState(false);
  return (
    <form
      onSubmit={(e) => {
        e.preventDefault(); // don't reload the page
        console.log("onSubmit");
        setSomeState(true);
      }}
    >
      {someState ? (
        <button
          type="button"
          onClick={() => {
            console.log("onClick");
            setSomeState(false);
          }}
        >
          button
        </button>
      ) : (
        null
      )}
      <button type="submit">submit</button>
    </form>
  );
}

In this case the code works as expected.

Also, giving keys to the elements solves the problem:

import { useState } from "react";

export default function App() {
  const [someState, setSomeState] = useState(false);
  return (
    <form
      onSubmit={(e) => {
        e.preventDefault(); // don't reload the page
        console.log("onSubmit");
        setSomeState(true);
      }}
    >
      {someState ? (
        <button
          key="one"
          type="button"
          onClick={() => {
            console.log("onClick");
            setSomeState(false);
          }}
        >
          button
        </button>
      ) : (
        <button key="two" type="submit">submit</button>
      )}
    </form>
  );
}
vxsl wrote this answer on 2022-11-19

@TNick

Seems that if you pull out the submit button the error is gone. In this case the code works as expected.

Yes, I think this shows that React is failing to reconcile the event handlers between the two buttons properly.

Also, giving keys to the elements solves the problem:

Yes, I mentioned this in my original post, but it should not be necessary.

More Details About Repo
Owner Name facebook
Repo Name react
Full Name facebook/react
Language JavaScript
Created Date 2013-05-24
Updated Date 2022-12-10
Star Count 198882
Watcher Count 6638
Fork Count 41302
Issue Count 1120

YOU MAY BE INTERESTED

Issue Title Created Date Comment Count Updated Date
AttributeError: 'list' object has no attribute '__module__' 0 2022-11-25 2022-12-02
Is the Typescript definition correct? 6 2020-12-24 2022-11-30
available package handling with flux in multi-tenant mode 3 2022-10-21 2022-11-08
Support all Metadata Annotations for Json Schema Milestone 1 2022-10-20 2022-11-09
Setup.bat not working 2 2022-06-24 2022-07-23
Not creating dist folder 1 2022-06-25 2022-07-23
"Repeated" benchmarks in pthread-wmm 0 2021-02-04 2022-09-09
No diagrams generated at all 1 2020-07-29 2022-10-15
[BUG Report]: Proxy docs not correct, please fix wasted hours on bad docs 2 2022-03-16 2022-10-29
Cannot deploy UI-provider properly on hardhat network 1 2021-12-12 2022-12-02
I18n translation exception 1 2021-06-02 2022-09-13
Webview reloads after being moved through the DOM. 0 2022-04-14 2022-12-09
`window.icon` of `package.json` does not work 5 2022-03-25 2022-10-26
Display console logs from multiple windows in the same Chromium DevTools window 1 2022-03-26 2022-11-26
my facebook presence doesnt work because of the website its because web.facebook.com instead of www.facebook.com 0 2022-04-29 2022-10-28
[BUG] Search results not colored 1 2021-11-25 2022-11-02
[Feature request] Associate "edit" for text extensions as Notepads instead of default Notepad. 2 2021-12-26 2022-11-08
Firefox can't play LL-DASH videos 3 2021-06-06 2022-11-12
[MenuButton] Confused about intended click away behaviour 4 2021-03-18 2022-11-08
leetcode41缺失的第一个正数-图挂了 1 2021-07-20 2022-12-06
Question about arbtrace_transaction behavior 1 2022-08-03 2022-10-10
Decimal not usable as Dict key: no hash method defined 5 2019-07-19 2022-12-02
Add SSH Tunnel options to Kafka Destination 3 2022-09-28 2022-10-29
NotAuthenticated: Authentication credentials were not provided. 0 2021-08-11 2022-12-01
add vue and apache echarts 1 2021-02-13 2022-10-13
[opentitanlib] FixedSizeBigInt to_bytes() methods should preserve byte length" 1 2022-09-09 2022-09-14
Wrong pos tag from Spanish es_dep_news_trf model (```VERB``` and ```AUX```) 3 2022-05-11 2022-10-15
x64 Sentry Binary in NuGet 6 2022-01-13 2022-11-07
[Bug]: Tabs component - maximum update depth exceeded 2 2022-06-10 2022-09-25
Add ability to sort by different columns on Circle visual 0 2021-07-23 2022-11-28
Ability to disable Guest Access 0 2021-02-24 2022-09-09
The Native build image are using java8 (should java 11) to compile the project 0 2021-01-19 2022-11-28
Let allow to use deepObject for arrays? 0 2020-12-30 2022-12-02
Intermediate HTML and CSS > Form Basics: Include Form Control Examples 7 2022-06-13 2022-09-15
"This app is blocked" and/or "Sign in with Google" temporarily disabled for this app 19 2020-12-08 2022-12-09
Account recovery request 1 2022-01-22 2022-12-08
Accounts Password Setting Server Hooks 5 2019-11-25 2022-11-29
🛑 Matomo is down 1 2021-09-08 2021-12-28
Highlighting with the mouse switches to visual mode 0 2021-09-08 2022-10-25
[BUG] 开启app后, 第一次与webdav服务器连接失败, 卡加载 5 2022-05-28 2022-11-21
RetroArch freezes my PS3 2 2022-06-19 2022-11-29
Wrong comparison results when using ProxyObject that is returning long for "valueOf" 2 2022-02-02 2022-10-24
jfrog rt bce or bag adds an unnecessary module id to a build info 3 2021-12-17 2022-11-09
Add support for `In` Label selector to Fabric8 mock Kubernetes server 1 2022-04-27 2022-11-17
"Hold to hide" on Always on top windows 0 2022-04-20 2022-11-12
Docs: update ast explorer links to point to playground 0 2021-12-27 2022-10-17
Cannot build from sources 4 2022-01-04 2022-10-31
fix footer 4 2021-02-27 2022-01-22
Node.createWithConfig Example 0 2021-02-11 2022-11-30
Invalid help link for AnnotateInternalApiRuleId (RS0055) (and couple other rules) 0 2022-11-12 2022-12-09