I have a form in one of my React components, and and in the outside component that calls it I want to pass a reference to a button there, so that I can also submit that usin
Edit: Simple and correct answer: https://stackoverflow.com/a/53573760/5271656
In React, data flows down and actions flow up. So notify child component about button click in the parent.
This is how you can do this.
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);
To me, this solution is hacky and not in a react way but serves your use-case.
Find working solution here:https://codesandbox.io/s/r52xll420m
You can achieve this by using regular HTML capabilities (HTML form Attribute), no need to use the React hacks:
Add "id" attribute to your form: id='my-form'
class CustomForm extends Component {
render() {
return (
<form id='my-form' onSubmit={alert('Form submitted!')}>
// Form Inputs go here
</form>
);
}
}
Then add the same Id to the "form" attribute of the target button outside of the form:
<button form='my-form' type="submit">Outside Button</button>
Now, the 'Outside Button' button will be absolutely equivalent as if it is inside the form.
Note: This is not supported by IE11.
You can pass the onSubmit click handler as a props as follows:
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);
Passing function as a props to handle form submit makes the CustomForm element more reusable since the business logic for the submit is not part of CustomForm component.
You can pass the submit function as a prop and use this method whenever you want. for more complex situations you can use redux save your form data on redux and whenever the button is clicked you read data from redux and submit them
None of these solutions worked for me, but I finally figured it out by doing
document.forms[0].submit()
Since there was only one form on the page, I selected it with the 0 index, but if there are multiple forms then you'd need to use the applicable index for the forms array.
You can set in the state a flag propery for example rootBtnClicked: false
and a method that handles the click in the App
component. Also in the <CustomForm />
, add a prop e.g. rootBtnClicked={this.state.rootBtnClicked}
. When "In Root" button is clicked, trigger that method; then the method changes the state with setState()
. Then inside the CustomForm
component's render()
method, check if the prop is true
. If it is, manually trigger .submit() using React's ref.