Как отправить форму с кнопки вне этого компонента в React?

У меня есть форма в одном из моих компонентов 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 кнопка нажата?

7 ответов

Решение

В 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

Вы можете добиться этого, используя обычные возможности HTML (атрибут HTML-формы), без использования хаков React:

Добавьте в форму атрибут id: id='my-form'

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

Затем добавьте тот же идентификатор к атрибуту "form" целевой кнопки вне формы:

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

Теперь кнопка "Внешняя кнопка" будет абсолютно такой же, как если бы она была внутри формы.

Примечание. IE11 не поддерживает это.

Вы можете установить в государстве флаг свойства, например rootBtnClicked: false и метод, который обрабатывает щелчок в App составная часть. Также в <CustomForm /> добавить опору, например rootBtnClicked={this.state.rootBtnClicked}, Когда нажата кнопка "In Root", запустите этот метод; тогда метод меняет состояние с setState(), Тогда внутри CustomForm компоненты render() метод, проверьте, если опора true, Если это так, вручную вызвать .submit() используя React's ref,

Итак, настройте кнопку с типом submit и атрибут form который имеет значение, равное id формы, которую вы хотите отправить

Вы можете передать обработчик кликов onSubmit в качестве реквизита следующим образом:

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.

Ни одно из этих решений не помогло мне, но я наконец понял это, выполнив

document.forms[0].submit()

Поскольку на странице была только одна форма, я выбрал ее с индексом 0, но если есть несколько форм, вам нужно будет использовать соответствующий индекс для массива форм.

Вы можете передать функцию submit в качестве реквизита и использовать этот метод в любое время. в более сложных ситуациях вы можете использовать redux, сохраняя данные формы на redux, и при каждом нажатии кнопки вы читаете данные из redux и отправляете их

Другие вопросы по тегам