Hi 🤓 Cảm ơn bạn đã ghé thăm blog này, nếu những bài viết trên blog giúp ích cho bạn. Bạn có thể giúp blog hiển thị quảng cáo bằng cách tạm ngừng ad blocker 😫 và để giúp blog duy trì hoạt động nếu bạn muốn.
Cảm ơn bạn!

useFormContext trong React Hook Form

Như các bạn đã biết để quản lý form, validation trong React Hook Form, chúng ta sẽ sử dụng 1 custom hook của React Hook Form có tên là useForm(). Dưới đây là một ví dụ:

import * as React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit } = useForm({
    defaultValues: {
      fullName: '',
      category: '',
      checkbox: [],
    }
  });

  return (
    <form onSubmit={handleSubmit(console.log)}>
      <input {...register("fullName", { required: true })} placeholder="Full name" />
      <select {...register("category")}>
        <option value="">Select...</option>
        <option value="A">Category A</option>
        <option value="B">Category B</option>
      </select>
      <input {...register("checkbox")} type="checkbox" value="A" />

      <input type="submit" />
    </form>
  );
}

Để truyền các giá trị từ 1 field vào form của React Hook Form thì chúng ta sẽ dùng register như ví dụ trên sau đó đặt field name là xong 😁.

Một vấn đề đặt ra đó là nếu chúng ta cần sử dụng register trong 1 nested component thì phải truyền register vào props của các component này và khi đó ta mới có thể lấy ra để sử dụng.

<A> // chứa useForm()
  <B>
    <C>
       <D /> // D muốn sử dụng register từ useForm() trong A
    </C>
  </B>
</A>

Như ví dụ trên thì nếu <D/> chứa input và các bạn muốn register nó vào form của React Hook Form thì lúc này chúng ta sẽ cần phải truyền register từ <A/> -> <B/> -> <C/>. Như vậy nếu như càng nhiều nested component thì chúng ta càng phải truyền nhiều. Điều này sẽ làm code chúng ta trông khá tệ 🤔.

Để giải quyết vấn đề này thì React Hook Form cung cấp cho chúng ta một custom hook được gọi là useFormContext. Nó sẽ giúp chúng ta tương tác với form context một cách dễ dàng hơn.

Về cách sử dụng chúng ta chỉ cần wrap component bằng FormProvider, và truyền các methods cho FormProvider.

import { useForm, FormProvider, useFormContext } from "react-hook-form";

export default function App() {
  const formHandler = useForm();
  const onSubmit = data => console.log(data);

  return (
    <FormProvider {...formHandler} >
      <form onSubmit={formHandler.handleSubmit(onSubmit)}>
        <NestedInput />
        <input type="submit" />
      </form>
    </FormProvider>
  );
}

function NestedInput() {
  const { register } = useFormContext(); // có thể gọi các method khác tại đây mà không cần truyền qua props
  return <input {...register("fullName")} />;
}

Các bạn có thể thấy khi dùng useFormContext chúng ta có thể truy xuất các method tại useForm() một cách dễ dàng đúng không 👏.

Tương tự như vậy ta sẽ giải quyết ví dụ trước đó mà không cần truyền register qua props:

<A> // chứa useForm(), const formHandler = useForm()
  <FormProvider {...formHandler} >
    <B>
      <C>
         <D /> // const { register } = useFormContext(); lấy register từ useForm() trong A dễ dàng 😍
      </C>
    </B>
  </FormProvider>
</A>

Trong trường hợp ta có nhiều FormProvider thì khi dùng useFormContext(), nó sẽ lấy method từ FormProvider gần nó nhất. Ở ví dụ trên nếu wrap C bằng FormProvider và khi D dùng useFormContext() thì method ở B (Giả sử) chứa useForm sẽ được lấy chứ không phải useForm trong A.

Kết luận

Hy vọng bài viết sẽ giúp ích được cho các bạn. Chúng ta sẽ cùng tìm hiểu về các API khác của React Hook Form trong các bài viết sắp tới nhé.

Cảm ơn các bạn đã dành thời gian đọc bài viết 🤞🎉.

Đọc thêm bài viết liên quan khác:

  1. Khác nhau giữa watch() vs useWatch() trong React Hook Form
Có thể bạn thích ⚡
homiedev
About Me

Hi, I'm @devnav. Một người thích chia sẻ kiến thức, đặc biệt là về Frontend 🚀. Trang web này được tạo ra nhằm giúp các bạn học Frontend hiệu quả hơn 🎉😄.

Chúc các bạn tìm được kiến thức hữu ích trong blog này 😁😁.