How to use react-hook-form inside class Component?

Viewed 8575

I use the following code to create a login page with form validation:

import React from 'react';
import { Button, Form, FormGroup, Label, Input } from 'reactstrap';
import { useForm } from 'react-hook-form';

class SignIn extends React.Component {
  
const { register, handleSubmit, errors } = useForm();
const onSubmit = data => console.log(data);
console.log(errors);

  render() {
    return (
      <div>
        <Form onSubmit={handleSubmit(onSubmit)}>

            <Label>Email : </Label>
            <Input type="email" placeholder="email" name="email" ref={register({required: true, pattern: /^\S+@\S+$/i})}></Input>

            <Label>Password : </Label>
            <Input type="password" placeholder="password"  name="password" ref={register({required: true, min: 8, maxLength: 20})}></Input>

        </Form>
      </div>
    );
  }
}


export default SignIn;

and I have a problem using react-hook-form inside the Class Component
My question, if it's possible, is: How to use the react-hook-form with Class Component without rewriting the code to the hook version?

5 Answers

You can't use hooks in react class components. The class that you provide looks small and I think that you can easily rewrite it to functional component. Perhaps you don't want to, you can provide hoc with useForm hook that wraps your class component.

export const withUseFormHook = (Component) => {
    return props => {
        const form = useForm();
        return <Component {...props} {...form} />
    }       
}

And in you SignIn component simply do:

export default withUseFormHook(SignIn);

The best and easiest way will be to change class Component, to a functional Component and use the useForm hook. Below you can find the example code:

import React from 'react'

import { Button, Form, FormGroup, Label, Input } from 'reactstrap';
import { useForm } from 'react-hook-form';

const SignIn = () => {

  const { register, handleSubmit, errors } = useForm();
  const onSubmit = data => console.log(data);
  console.log(errors);

  return (
    <>
      <div>
        <Form onSubmit={handleSubmit(onSubmit)}>

        <Label>Email : </Label>
        <Input type="email" placeholder="email" name="email" ref={register({required: true, pattern: /^\S+@\S+$/i})}></Input>

        <Label>Password : </Label>
        <Input type="password" placeholder="password"  name="password" ref={register({required: true, min: 8, maxLength: 20})}></Input>

        </Form>
      </div>
    </>
  )}

export default SignIn;

After searching more and more I used this solution :
Creating a separate file with the hook version :

import React from 'react'

import { Button, Form, FormGroup, Label, Input } from 'reactstrap';
import { useForm } from 'react-hook-form';

const SignInHook = () => {

    const { register, handleSubmit, errors } = useForm();
    const onSubmit = data => console.log(data);
    console.log(errors);



    return (
    <>
      <div>
        <Form onSubmit={handleSubmit(onSubmit)}>

            <Label>Email : </Label>
            <Input type="email" placeholder="email" name="email" ref={register({required: true, pattern: /^\S+@\S+$/i})}></Input>

            <Label>Password : </Label>
            <Input type="password" placeholder="password"  name="password" ref={register({required: true, min: 8, maxLength: 20})}></Input>

        </Form>
      </div>
    </>
   )
}

export default SignInHook

And Use it inside my Class Component:

import React from 'react';
import SignInHook from './SignInHook';

class SignIn extends React.Component {
  
  render() {
    return (
      <div>
        <SignInHook></SignInHook>
      </div>
    );
  }
}


export default SignIn;

I had the same issue but at the end I could solve it like this:

import React from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";

import "./styles.css";

class Login extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false
    };
    this.onSubmit = this.onSubmit.bind(this);
  }

  onSubmit(data) {
    console.log(data);
  }

  render() {
    const { register, handleSubmit, errors } = this.props;
    return (
      <form onSubmit={handleSubmit(this.onSubmit)}>
        <label>Example</label>
        <input name="example" defaultValue="test" ref={register} />
        <label>ExampleRequired</label>
        <input
          name="exampleRequired"
          ref={register({ required: true, maxLength: 10 })}
        />
        {errors.exampleRequired && <p>This field is required</p>}
        <input type="submit" />
      </form>
    );
  }
}

function App(props) {
  const form = useForm();
  return <Login {...props} {...form} />;
}

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

Here is the live sandbox.

Related