MDB React & React Hook Form intergration

MDB React & React Hook Form intergration

MDB React integration with React Hook Form. Configuration, various examples of implementation and much more.

RHF is a library that makes dealing with forms in React easy. It is built with performance in mind. It allows you to create forms with minimal code and it is easy to integrate with MDB React.

In this tutorial you will learn how to validate forms created with MDB React using RHF.


Install React Hook Form

To install RHF, run the following command in your project directory:

You can find more details in the official documentation.

npm i react-hook-form
yarn add react-hook-form

Basic example

In this form we will use the useForm hook to register inputs and handleSubmit to console log the form data. The function will not be called if a required field is empty.

import { useForm } from 'react-hook-form';
import { MDBInput, MDBSelect, MDBBtn } from 'mdb-react-ui-kit';
import { selectData } from './selectData';

export default function App() {
  const { register, handleSubmit, setValue } = useForm();
  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <MDBInput {...register('firstName', { required: true })} />
      <MDBSelect
        className='my-3'
        label='Gender'
        preventFirstSelection
        data={selectData}
        {...register('gender')}
        onChange={(opt) => setValue('gender', opt.value)}
      />
      <MDBBtn type='submit'>Submit</MDBBtn>
    </form>
  );
}
const selectData = [
  {
    text: 'male',
    value: 'male',
  },
  {
    text: 'female',
    value: 'female',
  },
  {
    text: 'other',
    value: 'other',
  },
];

export { selectData };

Default values

If the component you use has a value set by default, don't forget to pass it to the useForm hook.

import { useForm } from 'react-hook-form';
import { MDBInput, MDBSelect, MDBBtn } from 'mdb-react-ui-kit';
import { selectData } from './selectData';

export default function App() {
  const { register, handleSubmit, setValue } = useForm({
    defaultValues: {
      gender: 'male',
    },
  });
  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <MDBSelect
        label='Gender'
        data={selectData}
        {...register('gender')}
        onChange={(opt) => setValue('gender', opt.value)}
      />
      <MDBBtn type='submit'>Submit</MDBBtn>
    </form>
  );
}
const selectData = [
  {
    text: 'male',
    value: 'male',
  },
  {
    text: 'female',
    value: 'female',
  },
  {
    text: 'other',
    value: 'other',
  },
];

export { selectData };

Basic validation

register accepts an object as its second argument, which includes validation rules. There are many options available, but the most commonly used are:

  • required - field is required
  • minLength - minimum length
  • maxLength - maximum length
  • min - minimum value
  • max - maximum value
  • pattern - regex pattern
  • validate - custom function

The options can be passed with or without an error message.

<MDBInput
{...register("MDBInput", {
  minLength: 5
})}
/>
<MDBInput
  {...register("MDBInput", {
    minLength: {
      value: 5,
      message: "The text must be at least 5 characters long",
    }
  })}
/>

Copy the code from this snippet below to see how it works in practice. Open console and see how the error object changes.

import { useForm } from 'react-hook-form';
import { MDBInput, MDBBtn, MDBDatepicker } from 'mdb-react-ui-kit';
import { selectData } from './selectData';

export default function App() {
  const {
    register,
    handleSubmit,
    setValue,
    formState: { errors },
  } = useForm();

  console.log('errors', errors);
  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <MDBInput
        className='my-3'
        label='First name'
        {...register('firstName', {
          required: true,
          minLength: 2,
          maxLength: 10,
        })}
      />
      <MDBInput
        className='my-3'
        label='Last name'
        {...register('lastName', {
          required: true,
          minLength: 2,
          maxLength: 10,
        })}
      />
      <MDBDatepicker
        className='my-3'
        label='Date of visit'
        {...register('date', {
          required: true,
          pattern: /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/,
        })}
        onChange={(value) => setValue('date', value)}
      />
      <MDBBtn type='submit'>Submit</MDBBtn>
    </form>
  );
}
import { useForm } from 'react-hook-form';
import { MDBInput, MDBBtn, MDBDatepicker } from 'mdb-react-ui-kit';

export default function App() {
  const {
    register,
    handleSubmit,
    setValue,
    formState: { errors },
  } = useForm();

  console.log('errors', errors);
  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <MDBInput
        className='my-3'
        label='First name'
        {...register('firstName', {
          required: 'This field is required.',
          minLength: {
            value: 2,
            message: 'First name should be at least 2 characters long.',
          },
          maxLength: {
            value: 10,
            message: 'First name should be at most 10 characters long.',
          },
        })}
      ></MDBInput>
      <MDBInput
        className='my-3'
        label='Last name'
        {...register('lastName', {
          required: 'This field is required.',
          minLength: {
            value: 2,
            message: 'Last name should be at least 2 characters long.',
          },
          maxLength: {
            value: 10,
            message: 'Last name should be at most 10 characters long.',
          },
        })}
      ></MDBInput>
      <MDBDatepicker
        className='my-3'
        label='Date of visit'
        {...register('date', {
          required: 'This field is required.',
          pattern: {
            value: /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/,
            message: 'Date should be in format dd/mm/yyyy.',
          },
        })}
        onChange={(value) => setValue('date', value)}
      ></MDBDatepicker>
      <MDBBtn type='submit'>Submit</MDBBtn>
    </form>
  );
}

Invalid feedback

We already have some validation rules and different error messages. Let's check out how to display them.

Check this example.

import React from "react";
import { useForm } from "react-hook-form";
import { MDBInput, MDBBtn, MDBDatepicker } from "mdb-react-ui-kit";

export default function App() {
  const {
    register,
    handleSubmit,
    setValue,
    formState: { errors },
  } = useForm();

  console.log("errors", errors);
  const onSubmit = (data) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div className="position-relative pb-3">
        <MDBInput
          className={`${errors.firstName ? "is-invalid" : ""}`}
          label="First name"
          {...register("firstName", {
            required: "This field is required.",
            minLength: {
              value: 2,
              message: "First name should be at least 2 characters long.",
            },
            maxLength: {
              value: 10,
              message: "First name should be at most 10 characters long.",
            },
          })}
        />
        {errors.firstName && (
          <span className="invalid-feedback d-block">{errors.firstName.message}</span>
        )}
      </div>
      <div className="position-relative pb-3">
        <MDBInput
          className={`${errors.lastName ? "is-invalid" : ""}`}
          label="Last name"
          {...register("lastName", {
            required: "This field is required.",
            minLength: {
              value: 2,
              message: "Last name should be at least 2 characters long.",
            },
            maxLength: {
              value: 10,
              message: "Last name should be at most 10 characters long.",
            },
          })}
        />
        {errors.lastName && (
          <span className="invalid-feedback d-block">{errors.lastName.message}</span>
        )}
      </div>
      <div className="position-relative pb-3">
        <MDBDatepicker
          className={`${errors.date ? "is-invalid" : ""}`}
          label="Date of visit"
          {...register("date", {
            required: "This field is required.",
            pattern: {
              value: /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/,
              message: "Date should be in format dd/mm/yyyy.",
            },
          })}
          onChange={(value) => setValue("date", value)}
        />
        {errors.date && <span className="invalid-feedback d-block">{errors.date.message}</span>}
      </div>
      <MDBBtn className="mt-4" type="submit">
        Submit
      </MDBBtn>
    </form>
  );
}

Custom validation

Sometimes you may need to create a custom validation rule. You can do it by passing a function to the validate option.

import React, { useState } from 'react';
import { useForm } from 'react-hook-form';
import { MDBSelect, MDBBtn } from 'mdb-react-ui-kit';
import { selectData } from './selectData';

function App() {
  const [wasValidated, setWasValidated] = useState(false);
  const {
    handleSubmit,
    register,
    setValue,
    setError,
    clearErrors,
    formState: { errors },
  } = useForm();

  console.log('errors', errors);

  const onSubmit = (data) => console.log(data);

  return (
    <div className='col-md-6 mx-auto'>
      <form onSubmit={handleSubmit(onSubmit)} className='row align-items-center'>
        <div className='my-2 col-6 position-relative'>
          <MDBSelect
            label='Select at least 3 options'
            inputClassName={`${errors.MDBSelect ? 'is-invalid' : ''}`}
            multiple
            required
            invalidFeedback='You must select at least 3 options'
            preventFirstSelection
            {...register('MDBSelect', {
              validate: (options) => {
                if (!options || options.length < 3) {
                  return 'You must select at least 3 options';
                }
              },
            })}
            onChange={(e) => {
              clearErrors('MDBSelect');
              setValue('MDBSelect', e);
              if (!wasValidated) return;
              if (!e || e.length < 3) {
                return setError('MDBSelect', {
                  type: 'validate',
                  message: 'You must select at least 3 options',
                });
              }
            }}
            data={selectData}
          />
          {errors.MDBSelect &&
          <span className='invalid-feedback' style={{ display: 'block' }}>
            {errors.MDBSelect.message}
          </span>}
        </div>
        <MDBBtn onClick={() => setWasValidated(true)} type='submit'>
          Submit
        </MDBBtn>
      </form>
    </div>
  );
}

export default App;
const selectData = [
  { text: 'Tony Stark', value: 'Ironman' },
  { text: 'Bruce Wayne', value: 'Batman' },
  { text: 'Clark Kent', value: 'Superman' },
  { text: 'Peter Parker', value: 'Spiderman' },
  { text: 'Steve Rogers', value: 'Captain America' },
];

export { selectData };