Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
August 14, 2021 08:46 am GMT

Form validation with react-hook-form

Form is one of core functionalities that must exist in any application. This functionality allows us interact with user data (input) and process it into a valuable data or resource (output).

Even this functionality is powerful, it has one biggest obstacle. Yes, it's how to validate the user input. And that's the reason why I make this article.

In this article I will share to you how we can handle form validation specifically in React application using a package called react-hook-form.

Let's start it out!

Requirements

  • React application (fresh or existing app)

NOTE:
I will use my previous project called example-app. It has no features. Just a fresh React project installed using CRA.

Steps

1. Add react-hook-form

I use Git inside example-app. So, before adding the package I will create a new branch called feat-signin then merge that feature into branch main whenever I finish that feature.

# Create and checkout to branch feat-signingit checkout -b feat-signin

Now, it's time to add the package.

yarn add react-hook-form

2. Create the form

Maybe you have a clue about what form that I want to build. Yes, it's a sign-in form. I will validate the user email and password before they can actually sign-in.

I will not using any styling tools. Just HTML to make it simple and focus :).

First, I wanna add a page called Signin inside my project.

# Here's my current project. package.json public  favicon.ico  index.html  logo192.png  logo512.png  manifest.json  robots.txt README.md src  App.css  App.js  App.test.js  index.css  index.js  logo.svg  pages   Signin.js  reportWebVitals.js  setupTests.js yarn.lock

Create the sign-in form and import it inside App.js.

// pages/Signin.jsfunction Signin() {  return (    <div>      <form>        <div>          <label htmlFor="email">Email</label>          <input type="email" id="email" />        </div>        <div>          <label htmlFor="password">Password</label>          <input type="password" id="password" />        </div>        <div>          <button>Signin</button>        </div>      </form>    </div>  );}export default Signin;
// App.jsimport Signin from './pages/Signin';function App() {  return <Signin />;}export default App;

3. Integrate the form with react-hook-form

Let's integrate the previous form so we can collect all user input inside that form.

// pages/Signin.jsimport { useForm } from 'react-hook-form';function Signin() {  const {    register,    handleSubmit,    formState: { errors },  } = useForm();  const onSubmit = (form) => {    console.log(form);  };  return (    <div>      <form onSubmit={handleSubmit(onSubmit)}>        <div>          <label htmlFor="email">Email</label>          <input type="email" id="email" {...register('email')} />        </div>        <div>          <label htmlFor="password">Password</label>          <input type="password" id="password" {...register('password')} />        </div>        <div>          <button>Signin</button>        </div>      </form>    </div>  );}export default Signin;

Run the application, open the browser console and try to submit the form. You will see something like image below.
Submit form

4. Add input validation

If I submit the form with an empty password, I will not get any error message that indicate I forgot to input my password which is a bad UX.
Forgot to input password

To achieve that feature, we need to install two packages. @hookform/resolvers/yup and yup.

yarn add @hookform/resolvers yup

NOTE:
yup is one of JavaScript schema Objects. It allows us to define a shape (structure) and validate a JavaScript object. You can also use other schema object like Joi, Zod, etc.

Now, let's add input validation into the form.

// pages/Signin.js// ...import { yupResolver } from '@hookform/resolvers/yup';import * as yup from 'yup';const schema = yup.object().shape({  email: yup.string().email().required(),  password: yup.string().required(),});function Signin() {  const {    register,    handleSubmit,    formState: { errors },  } = useForm({ resolver: yupResolver(schema) });// ...}// ...

Now, if we submit the form with an empty password, we will not see any message in the browser console because the form is actually throw error messages and not submit the form.
Form error

Look, even the cursor automatically focus to the input element that produce the error.

5. Displaying the error messages

Now, the form can validates the input value, but it's not good enough. We need to display what's wrong with the form. So, the user can input the correct value.

// pages/Signin.js<div>  <label htmlFor="email">Email</label>  <input type="email" id="email" {...register("email")} />  {errors.email?.message && <span>{errors.email.message}</span>}</div><div>  <label htmlFor="password">Password</label>  <input type="password" id="password" {...register("password")} />  {errors.password?.message && <span>{errors.password.message}</span>}</div>

Submit the form and we can see the error messages.
Form with error messages

Hmm, I think the error messages not user friendly enough, right? So, let's improve it.

6. Customize the error messages

This is the reason why I choose Yup for the schema validation. We can easily customize the error messages like this.

// pages/Signin.js// ...const schema = yup.object().shape({  email: yup    .string()    .email('Please provide a valid email address')    .required('Please provide your email address'),  password: yup.string().required('Please provide your password'),});// ...

Submit the form again and you will see the error messages has changed.
Improved error messages

Bonus

Validating the form on the client side is not enough. We also need to validate the form on the server side because attacker can bypass our validation on the client side.

The problem comes when we want to display the error messages from the server into the form. Fortunately, we can easily done this feature using react-hook-form.

We just need to use setError API to display the error messages that comes from the server into the form.

// pages/Signin.js// Response from the server// {//   "message": "...",//   "errors": {//     email: ["The email must be a valid email address."]//   }// }// ...const {  register,  handleSubmit,  formState: { errors },  setError,} = useForm({ resolver: yupResolver(schema) });const onSubmit = async (form) => {  // Do sign-in process. Just example :)  await Http.post(/** ... */);  if ((await Http.status()) === 422) {    let res = await Http.response();    for (let [field, messages] of Object.entries(res.errors)) {      setError(field, { type: 'manual', message: message.join(' ') });    }  }  // ...};// ...


Original Link: https://dev.to/thexdev/form-validation-with-react-hook-form-94e

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To