Using React Hook Form in React

min read

Day 41/100 #100DaysOfCode #React #ReactNative

Nay tiếp tục tìm hiểu về các modules hooks được sử dụng nhiều trong React. Mình thấy một số bạn dùng react-hook-form để lưu dữ liệu của form nhập sau đó submit đển server
Thông thường mình chỉ biết tạo các state cho field trong form, rồi tạo phương thức onChange để setState lại các field tương ứng cho form, tốn khá nhiều thời gian

Dưới đây là hình Demo tí xíu mình làm

Using React Hook Form in React

Ta có thể sử dụng react-hook-form để xử lý form nhập, rồi việc của ta chỉ là đưa data đó vào (axios,fetch) request đến server thôi

Cài đặt modules react-hook-form như sau:

npm install react-hook-form

Sau khi cài xong sử dụng cũng khá đơn giản lắm, import module vào file component cần dùng

import { useForm } from "react-hook-form";

Tạo biến hứng từ useForm()

const { register, handleSubmit } = useForm();

Còn form ta cấu hình như sau:

const onSubmit = data => console.log(data);
return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName")} />
      <select {...register("gender")}>
        <option value="female">female</option>
        <option value="male">male</option>
        <option value="other">other</option>
      </select>
      <input type="submit" />
    </form>
  );

Các bạn thấy bên trên, ta có dùng onSubmit trong element form và thiết lập sự kiện submit

 <form onSubmit={handleSubmit(onSubmit)}></form>

Cấu hình các field cho các thẻ input

<input {...register("firstName")} />

Bên cạnh đó ta cũng có thể cấu hình (required,pattern) cho các field luôn nhé

<input {...register("firstName", { required: true, maxLength: 20 })} />
<input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} />
<input type="number" {...register("age", { min: 18, max: 99 })} />
<input {...register("email", { required: true, pattern: /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/})} />

Okay bắt đầu thôi, giờ mình tạo file ReactHookForm.js trong project

import React, {useState, useRef } from "react";
import { useForm } from "react-hook-form";
import "./styles.css";
const ReactHookForm = () => {
  const [dataJson, setDataJson] = useState({});
  const [success, setSuccess] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const {
    register,
    handleSubmit,
    formState: { errors },
    getValues,
  } = useForm({});

  /** Form submit */
  const onRegister = (data) => {
    setDataJson(data);
    setIsLoading(true);
    const requestOptions = {
      method: "POST",
      headers: new Headers({
        "Content-Type": "application/json",
      }),
      body: JSON.stringify(dataJson),
    };
    fetch(`http://127.0.0.1:8000/api/users/register`,requestOptions)
     .then(res => res.json())
     .then(json =>{
         console.log(json);
         if(json.success==1) setSuccess(true)
     });
  };
  

  const Select = React.forwardRef(({ onChange, onBlur, name, label }, ref) => (
    <>
      <label>Male,female</label>
      <select name={name} ref={ref} onChange={onChange} onBlur={onBlur}>
        <option value="0">Male</option>
        <option value="1">Female</option>
      </select>
    </>
  ))

  return (
    <>
      <div className="form-register">
        <form onSubmit={handleSubmit(onRegister)}>
          <h2>Form Register</h2>
          <div className="label-name">
            <label>Firstname</label>
            <input
              {...register("firstname", { required: true, maxLength: 20 })}
            />
            {errors?.firstname?.type === "required" && (
              <p>This field is required</p>
            )}
            {errors?.firstname?.type === "maxLength" && (
              <p>First name cannot exceed 20 characters</p>
            )}
          </div>
          <div className="label-name">
            <label>LastName</label>
            <input
              {...register("lastname", {
                required: true,
                pattern: /^[A-Za-z]+$/i,
              })}
            />
            {errors?.lastname?.type === "required" && (
              <p>This field is required</p>
            )}
            {errors?.lastname?.type === "pattern" && (
              <p>Alphabetical characters only</p>
            )}
          </div>
          <div className="label-name">
            <Select label="Male-female" {...register("choosesex")} />
          </div>
          <div className="label-name">
            <label>Age</label>
            <input type="number" {...register("age", { min: 18, max: 99 })} />

            {errors.age && <p>"Age [18-99]"</p>}
          </div>

          <div className="label-name">
            <label>Email</label>
            <input
              {...register("email", {
                required: true,
                pattern: /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/,
              })}
            />
            {errors?.email?.type === "required" && (
              <p>This field is required</p>
            )}
            {errors?.email?.type === "pattern" && <p>Email error</p>}
          </div>
          <div className="label-name">
            <label>Password</label>
            <input
              type="password"
              {...register("password",{required:true})}
            />
            {errors?.password && <p>Enter password</p>}
          </div>
          <div className="label-name">
            <label>Confirm Password</label>
            <input type="password"
              {...register("password_repeat",  {validate: (value) => {
              const { password } = getValues();
              return password === value || "Passwords should match!";
            }})} />
            {errors.password_repeat && <p>{errors.password_repeat.message}</p>}
          </div>

          <button>Submit form</button>
        </form>
        {success && <h3>You register success!</h3>}

        {isLoading && (
          <div className="out-json">
            <pre>{JSON.stringify(dataJson)}</pre>
          </div>
        )}
      </div>
    </>
  );
};

export default ReactHookForm;

Mình nói sơ qua về đoạn mã trên như sau, mình tạo các state để check kiểm tra dữ liệu

const [dataJson, setDataJson] = useState({});  //update datajson after call request api
const [success, setSuccess] = useState(false);  // update success after call api
const [isLoading, setIsLoading] = useState(false); // user click button submit form

Khởi tạo useForm()

const { register, handleSubmit, formState: { errors },getValues} = useForm({});

+ register : giúp ta cấu hình các chức năng require, pattern, maxLength,minLength,...
+ handleSubmit : dùng bắt sự kiện onclick submit form
+ formState : { errors } : cấu hình thông số báo lỗi
+ getValues : giúp ta lấy giá trị hiện tại
+ reset :  dùng reset lại form

Các bạn có thể tìm hiểu thêm tại đây :  React Hook Form

Các hiện thị thông báo lỗi của field như sau:

{errors?.firstname?.type === "required" && (
    <p>This field is required</p>
}
errors?.firstname?.type === "maxLength" && (
      <p>First name cannot exceed 20 characters</p>
)}

Kiểm tra passwordpassword_repeat có đúng với nhau không, ta cần phải sử dụng getValue để lấy giá trị so sánh với nhau, có nhiều cách để làm vấn đề này, bạn có thể search từ khoá "password confirm in react hook form"

 <input type="password" {...register("password",{required:true})} />
 <input type="password"
              {...register("password_repeat",  {validate: (value) => {
              const { password } = getValues();
              return password === value || "Passwords should match!";
            }})} />

Using React Hook Form in React

Có nhiều cái hay trong module react hook form, các bạn có thể lên trang chính để tìm hiểu thêm nhé

x

Ủng hộ tôi bằng cách click vào quảng cáo. Để tôi có kinh phí tiếp tục phát triển Website!(Support me by clicking on the ad. Let me have the money to continue developing the Website!)