【问题标题】:How to submit form from a button outside that component in React?如何从 React 中该组件外部的按钮提交表单?
【发布时间】:2023-04-04 05:19:01
【问题描述】:

我的一个 React 组件中有一个表单,在调用它的外部组件中,我想传递一个对那里的按钮的引用,以便我也可以使用该按钮提交它。

为了更清楚,我有以下几点:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class CustomForm extends Component {
  render() {
    return (
      <form onSubmit={alert('Form submitted!')}>
        <button type='submit'>Inside Custom</button>
      </form>
    );
  }
}

function App() {
  return (
    <div>
      <CustomForm />
      <button>In Root</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

现在,我可以使用标题为“Inside Custom”的按钮提交表单,但我也希望能够使用位于根组件中的标题为“In Root”的按钮提交表单。有没有办法以某种方式将该按钮的引用传递给该自定义组件,并在单击In Root 按钮时实际提交表单?

【问题讨论】:

标签: reactjs


【解决方案1】:

您可以通过使用常规 HTML 功能 (HTML form Attribute) 来实现这一点,无需使用 React hacks:

在表单中添加“id”属性:id='my-form'

class CustomForm extends Component {
    render() {
        return (
             <form id='my-form' onSubmit={alert('Form submitted!')}>
                // Form Inputs go here    
             </form>
        );
    }
}

然后在表单外的目标按钮的“form”属性中添加相同的Id:

<button form='my-form' type="submit">Outside Button</button>

现在,“外部按钮”按钮将完全等同于它在表单内部。

注意:IE11 不支持此功能。

【讨论】:

  • 你知道我们有什么方法可以让这个在 IE11 中工作吗? @pubudu
  • @Vidur 不幸的是没有。我强烈推荐解决方案,该解决方案建议将handleSubmit 作为父母的道具传递给您。此解决方案甚至适用于 IE8 等旧版浏览器
【解决方案2】:

编辑:简单而正确的答案:https://stackoverflow.com/a/53573760/5271656

在 React 中,数据向下流动,动作向上流动。因此,通知子组件有关在父项中单击按钮的信息。
这就是你可以做到这一点的方法。

import React, { Component } from "react";
import ReactDOM from "react-dom";

class CustomForm extends Component {
  handleOnSubmit = e => {
    e.preventDefault();
    // pass form data
    // get it from state
    const formData = {};
    this.finallySubmit(formData);
  };

  finallySubmit = formData => {
    alert("Form submitted!");
  };

  componentDidUpdate(prevProps, prevState) {
    if (this.props.submitFromOutside) {
      // pass form data
      // get it from state
      const formData = {};
      this.finallySubmit();
    }
  }

  render() {
    return (
      <form onSubmit={this.handleOnSubmit}>
        <button type="submit">Inside Custom</button>
      </form>
    );
  }
}

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      submitFromOutside: false
    };
  }
  submitCustomForm = () => {
    this.setState({
      submitFromOutside: true
    });
  };

  componentDidMount() {
    console.log(this.form);
  }

  render() {
    return (
      <div>
        <CustomForm submitFromOutside={this.state.submitFromOutside} />
        <button onClick={this.submitCustomForm}>In Root</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);  

对我来说,这个解决方案很老套,不是反应方式,而是为您的用例服务。
在这里找到工作解决方案:https://codesandbox.io/s/r52xll420m

【讨论】:

  • 顺便说一句,你为什么说这不是一种反应方式,而是一种 hacky 解决方案?
  • 但我不明白为什么要在 CustomForm 组件中提供提交功能,那么为什么不能简单地在 App 组件中制作它并作为道具传递给自定义表单组件?
  • @BhojendraRauniyar 正确的方法是将函数传递给孩子,孩子会在提交时调用它。但是要回答 OP 的用例,这是我能想到的唯一解决方案。 ref 也可以使用,但这需要向父级发送表单值
【解决方案3】:

您可以在状态中设置一个标志属性,例如rootBtnClicked: false 和一个处理App 组件中的点击的方法。同样在&lt;CustomForm /&gt; 中,添加一个道具,例如rootBtnClicked={this.state.rootBtnClicked}。单击“In Root”按钮时,触发该方法;然后该方法使用setState() 更改状态。然后在CustomForm 组件的render() 方法中,检查prop 是否为true。如果是,请使用 React 的 ref 手动触发 .submit()

【讨论】:

  • 您可以在回答问题时尝试提供代码示例。只是说,它可以帮助人们更好地理解你的意思。
【解决方案4】:

这些解决方案都不适合我,但我最终通过这样做弄明白了

document.forms[0].submit()

由于页面上只有一个表单,因此我选择了索引为 0 的表单,但如果有多个表单,则需要为表单数组使用适用的索引。

【讨论】:

    【解决方案5】:

    您可以将 onSubmit 点击处理程序作为 props 传递,如下所示:

    import React, { Component } from "react";
    import ReactDOM from "react-dom";
    
    class CustomForm extends Component {
    
      render() {
        return (
          <form onSubmit={this.props.handleSubmit}>
            <button type='submit'>Inside Custom</button>
          </form>
        );
      }
    }
    
    function App() {
     handleSubmit = () => {
       alert('Form submitted!')
    }
      return (
        <div>
          <CustomForm onSubmit={this.handleSubmit} />
          <button>In Root</button>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    

    将函数作为处理表单提交的道具传递使 CustomForm 元素更具可重用性,因为提交的业务逻辑不是 CustomForm 组件的一部分。

    【讨论】:

    • 这不是 OP 想要的。在App 组件中的解决方案按钮中不会调用CustomForm 中的表单提交
    • @MurliPrajapati 啊,我明白了,我实际上是用 React 方式做的,谢谢指点。
    • 提交按钮必须在表单之外。因此,这个答案没有帮助。
    【解决方案6】:

    您可以将提交函数作为道具传递,并在需要时使用此方法。 对于更复杂的情况,您可以使用 redux 将表单数据保存在 redux 上,每当单击按钮时,您都会从 redux 读取数据并提交它们

    【讨论】:

      【解决方案7】:

      好吧,设置一个类型为submit 和属性form 的按钮,其值等于您要提交的表单的id

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-06
        • 1970-01-01
        • 2012-01-03
        • 1970-01-01
        • 2020-01-18
        • 2017-10-19
        • 2019-09-25
        • 2019-12-11
        相关资源
        最近更新 更多