最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React JS, two submit buttons in one form - Stack Overflow

programmeradmin7浏览0评论

When using React JS, how can I identify which button was used to submit the form?

I thought something like this would work, but it doesn't:

export default function App() {
  const onSubmit = e => {
    e.preventDefault();
    console.log(e.target.btn.value);
  };

  return (
    <form className="App" onSubmit={onSubmit}>
      <button type="submit" name="btn" value="wow">
        Button 1
      </button>
      <button type="submit" name="btn" value="oh no">
        Button 2
      </button>
    </form>
  );
}

Code sandbox

According to standard HTML you should be able to name two buttons the same name? Or use formaction attribute to distinguish them.

In my use case the buttons don't have knowledge about the form. I want to avoid a solution where I use some temporary state to remember which button was clicked.

In standard HTML you can do this:

<form action="/action_page.php">
  <input type="submit" name="btn" value="Submit">
  <input type="submit" name="btn" value="Submit2">
</form> 

When you submit the form btn will either be posted Submit or Submit2 depending on which button you click. I want to get as close as possible to this standard when building my React form. Use as little help from Javascript and React as possible. Basically just add the buttons to the DOM inside my form and collect the values from the event that I have access to inside of the submit handler.

When using React JS, how can I identify which button was used to submit the form?

I thought something like this would work, but it doesn't:

export default function App() {
  const onSubmit = e => {
    e.preventDefault();
    console.log(e.target.btn.value);
  };

  return (
    <form className="App" onSubmit={onSubmit}>
      <button type="submit" name="btn" value="wow">
        Button 1
      </button>
      <button type="submit" name="btn" value="oh no">
        Button 2
      </button>
    </form>
  );
}

Code sandbox

According to standard HTML you should be able to name two buttons the same name? Or use formaction attribute to distinguish them.

In my use case the buttons don't have knowledge about the form. I want to avoid a solution where I use some temporary state to remember which button was clicked.

In standard HTML you can do this:

<form action="/action_page.php">
  <input type="submit" name="btn" value="Submit">
  <input type="submit" name="btn" value="Submit2">
</form> 

When you submit the form btn will either be posted Submit or Submit2 depending on which button you click. I want to get as close as possible to this standard when building my React form. Use as little help from Javascript and React as possible. Basically just add the buttons to the DOM inside my form and collect the values from the event that I have access to inside of the submit handler.

Share Improve this question edited Jan 17, 2023 at 10:31 icc97 12.7k9 gold badges83 silver badges96 bronze badges asked Feb 22, 2020 at 6:50 JohnJohn 2,2025 gold badges31 silver badges51 bronze badges 5
  • 2 Why not use onClick for each button? You can have a separate handler for each, or pass an argument to a shared handler. – Michael Yaworski Commented Feb 22, 2020 at 7:07
  • what are you trying to achieve? why do you want to use 2 submit buttons? – hiddenuser.2524 Commented Feb 22, 2020 at 7:09
  • I want to add buttons in a declarative way and then collect the form data that was submitted. In my use case the buttons have no knowledge about the form. I want to work with the form in a standard way, but I want to intercept the submit event and post the data myself with an AJAX request, and not use the form action and method. – John Commented Feb 22, 2020 at 7:23
  • Which solution did you go for in the end? – Manuel Jacob Commented Feb 11, 2021 at 12:40
  • @ManuelJacob I went with a state within the component that I toggle. – John Commented Mar 24, 2021 at 11:58
Add a comment  | 

6 Answers 6

Reset to default 28

Try using event.submitter.name property. Add different name to your buttons and check their names in eventHandler. If you use some kind of library for making forms it may lay in e.nativeEvent.submitter.name
More info https://developer.mozilla.org/en-US/docs/Web/API/SubmitEvent/submitter

e.nativeEvent.submitter.name;

Worked for me.

Working with forms in ReactJS is rather straight forwards, if you know how input works. Here is some more information directly from the documentation: https://reactjs.org/docs/forms.html

And here is a small example which I will explain for you:

      // You need to add a onSubmit event to the form. This will trigger when you submit the for as you do any other html form (including pressing the submit button)
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          // need to save input value somewhere (use the state for this, check the link from above
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        // this is your button, as with other html forms.
        <input type="submit" value="Submit" />
      </form>

In the case you described, you shouldn't really submit the data inside the buttons (why would you do that?), but instead submit the form data inside inputs. If you really want two buttons for submit (although a form can be submitted by hitting the key enter for example), you can do so like this:

    // onSubmit is the same as before, handle form data here
    <form className="App" onSubmit={onSubmit}>
      // setSubmitButton would set the submit button to button1 (e.g. use react state for this)
      <button type="submit" onClick={setSubmitButton('button1')} name="btn" value="wow">
        Button 1
      </button>
      <button type="submit" onClick={setSubmitButton('button2')} name="btn" value="oh no">
        Button 2
      </button>
    </form>

You can determine which button was clicked by checking which element currently has focus using document.activeElement in the onSubmit function. Add different ids or data attributes to the buttons to determine which one was clicked.

Either you can try the below code or you can try to make separate calls for both buttons.

Demo link codesandox

import React from "react";
import "./styles.css";

export default function App() {
  const state = {
    button: 1
  };

  const onSubmit = e => {
    e.preventDefault();
    if (state.button === 1) {
      console.log("Button 1 clicked!");
    }
    if (state.button === 2) {
      console.log("Button 2 clicked!");
    }
  };

  return (
    <form className="App" onSubmit={onSubmit}>
      <button
        onClick={() => (state.button = 1)}
        type="submit"
        name="btn1"
        value="wow"
      >
        Button 1
      </button>
      <button
        onClick={() => (state.button = 2)}
        type="submit"
        name="btn2"
        value="oh no"
      >
        Button 2
      </button>
    </form>
  );
}

I use e.nativeEvent.submitter. As long as react/nextjs do not support it, I use the following kludge to make typescript happy:

function getSubmitter(e: Event & { submitter?: HTMLButtonElement} ):
    HTMLButtonElement|undefined
{
    return e?.submitter;
}

function example(): JSX.Element {
    const handleSubmit = async (e:  React.FormEvent<HTMLFormElement>):
        Promise<void> =>
    {
        e.preventDefault();
        var btn = getSubmitter(e.nativeEvent);
        if (btn?.id == 'clear') {
            clearScreen();
            return;
        }
        //...
    }

    return (
        <form action='/check' method='post' onSubmit={handleSubmit}>
            <button type="submit" id="clear">Clear Screen</button>
            <button type="submit" id="store">Store</button>
            // ...
        </form>
    )
}
发布评论

评论列表(0)

  1. 暂无评论