'Submitting form from parent component

I would like to create a form where the submit button is located in the header. I'm currently using react-hook-forms but am having difficulties being able to submit the form from a component that is in the layout the displays the form (or child). I've included an image that may help visualize what im talking about.

enter image description here

Is there a way I can pass that form data or handleSubmit from react-hook-form to to the header that would then run the onSubmit when clicked?



Solution 1:[1]

You may want to investigate redux form and/or connect()

Example:

import React from 'react';
import { useForm } from 'react-hook-form';
import { connect } from 'react-redux';
 
const Form = ({ register, handleSubmit }) => {
  const methods = useForm();

  return (
    <form onSubmit={handleSubmit(register)}>...</form>
  );  
}; 

const mapDispatchToProps = dispatch => ({
  register: (data) => dispatch(register(data))
});
 
export default connect(null, mapDispatchToProps)(Form);

import React from 'react';
import { useForm } from 'react-hook-form';
import { connect } from 'react-redux';
 
const Form = ({ register, handleSubmit }) => {
  const methods = useForm();

  return (
    <form onSubmit={handleSubmit(register)}>...</form>
  );  
}; 
export default connect(null, mapDispatchToProps)(Form);

Solution 2:[2]

The simplest way to do this is by raising the form state to the closest parent between the two components, then you can pass the change and submit handlers down to the requisite components.

See https://reactjs.org/docs/lifting-state-up.html

In the case of react-hook-form that means calling useForm in that highest shared component and passing down the functions, ideally using composition instead of prop drilling

Solution 3:[3]

Just create a ref in the parent component, send it to the child component and assign that ref to an invisible submit button.

Finally, in the onClick event of the parent submit button simply call submitRef.current.click()

// ./From.js
import React from 'react';
import { useForm } from 'react-hook-form';

// This is the child component with a ref received from the parent
// and assigned to an invisible submit button 
const Form = ({ submitRef }) => {
  const {register, setValue, getValues, ...other } = useForm();

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      ...
      <button ref={submitRef} type="submit" style={{ display: 'none' }} />
    </form>
  );  
}; 


export default Form;
// ./Parent.js
import React, { useRef } from 'react';
import Form from './Form'
 
const Parent = () => {
  const submitRef = useRef();

  return (
    <>
      <button onClick={() => submitRef.current.click()}>Submit</button>
      <Form submitRef={submitRef}/>
    </>
  );  
}; 
export default Parent;

Solution 4:[4]

function handleForm(e) {
e.preventDefault()
// your code here
}

<button onClick={()=>{document.forms[0].submit()}} >Submit</button>

<form onSubmit={handleForm} >...</form>


For haters who dislike the answer:

const formRef=useRef();

function handleForm(e) {
e.preventDefault()
// your code here
}

<button onClick={()=>formRef.current.submit()} >Submit</button>

<form ref={formRef} onSubmit={handleForm} >...</form>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PJMan0300
Solution 2 coagmano
Solution 3 Javier
Solution 4