【问题标题】:How to submit a form through onSubmit event handler如何通过 onSubmit 事件处理程序提交表单
【发布时间】:2024-05-29 16:05:02
【问题描述】:

我有一个带有 onSubmit 函数和“提交”输入的 ReactJS 表单,如下所示。

<Form id="addItem" method="post"
  onSubmit={this.handleSubmit}>
  <Form.Group>
    <Form.Row>
      <Col xs={6}>
.
.
.
  </Form.Group>
  <Form.Control type="submit" id="addItemSubmit" name="add" value="Submit" />

handleSubmit 函数应该执行 HTML5 验证未涵盖的验证,然后将表单提交给 API。函数handleSubmit如下

handleSubmit(e) {
    e.preventDefault();
    let isValid = validateAddItemForm(this);
    if (isValid) {
      console.log(isValid);
      //const url = "/api/addItem/" + this.props.matchId;
      console.log("match offer url : " + props);
      const res = fetch(url, {
        method: 'post',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'X-CSRFToken': csrftoken
        },
        body: JSON.stringify({
         id: 0,
        }) 
       })
       .then((response) => response.json())
       .then((responseJson) => {
         return null;
       })
       .catch((error) => {
         console.error(error);
       });
    } else {
      console.log(isValid);
      return isValid;
    }
  }

现在我有两个问题。 如何将道具传递给handleSubmit?我需要从当前组件中传递一些道具来为获取请求完全生成正确的 URL。 如何在获取请求的“正文”中传递表单字段?当单击提交按钮时,填充的表单是否可用作 handleSubmit 函数的对象?还是我需要使用 document.getElementById().value 收集各个字段的值并将其传递到正文中?

编辑:我目前正在使用表单验证函数中的 document.getElementById 访问每个表单字段。这似乎不是一个好主意。这就是为什么我想尽可能将它作为一个对象来访问。

【问题讨论】:

  • 我认为 react 使用 onClick 代替并防止默认提交。
  • Forma 值应该从 props 传递,或者在可以使它们在组件中的任何地方都可以访问的状态下传递。
  • onSubmit 似乎也有效。当用户单击提交按钮然后代码通过表单验证时,不会提交表单。但是,如果我必须使用 onClick,那么它将在提交按钮上进行。仍然存在的问题是如何传递 Component 的 props 来形成 url 以及如何访问表单字段?
  • 表单字段值应保持在相同组件的状态或父组件的状态下传递给道具。
  • 你能举个例子说明如何做到这一点吗?

标签: javascript reactjs


【解决方案1】:

首先,您可以使用“this.props.propName”在组件上的任何地方访问组件的 props。您只需要记住,如果您在组件方法中使用“this”关键字,则必须绑定它(在构造函数或其他方法上)或使用箭头函数而不是类方法。

您还可以通过使用事件对象传递的表单本身使用 onSubmit 访问表单字段,您可以使用 event.target.elements 获取表单控件(输入、按钮、选择等)的数组

最后,如果你想提交表单,你可以在你的 handleSubmit 中使用 submit() 方法,再次使用你从事件中获得的表单,如下所示:event.target.submit()。但我可以看到您正在使用 fetch API,所以就像您已经提交了这样的表单。您可以尝试将表单标签上的 url 设置为 action 属性,如果通过了您的验证,则使用 submit() 提交表单。

More info on the submit() method on W3Schools

More info on accessing form.elements on W3Schools

Binding functions to components - to use "this" keyword inside them

例如:

<Form id="addItem" method="post" action={`/api/addItem/${this.props.matchId}`} onSubmit={this.handleSubmit}>
  <Form.Group>
    <Form.Row>
      <Col xs={6}>
.
.
.
  </Form.Group>
  <Form.Control type="submit" id="addItemSubmit" name="add" value="Submit" />
  
  
  
  handleSubmit = (e) => {
    e.preventDefault();
    // Your validation logic here
    // You can use e.target.elements to access the array of the form controls
    if (isValid) {
      e.target.submit(); //submitting the form to the link in action
    } else {
      console.log('Errors on form');
    }
  }

另一方面,正如其他人已经对您的问题发表评论的那样,您可以将您的组件设置为受控组件,这基本上意味着每个表单控件都将在您的状态上有一个值,并且您将可以访问所有字段值状态。

Controlled components from ReactJS Docs

【讨论】:

  • 完美运行。
  • 很好地回答了这个问题。但是 @user1933205 ,您应该考虑使用 ajax 调用 POST 请求,这样您就可以在不离开页面的情况下等待响应。提交表单将导致它离开页面并重新加载同一页面或另一个页面。您将失去 bes React 的优势,即重新渲染已更改页面的确切部分。通过等待响应,您可以显示成功消息、隐藏表单和/或使用 React Router 进行内部重定向,所有这些都无需离开页面。干得好!