Post

React-Hook-Form(1) - 기본 사용방법 알아보기

📌시작하며

이번 프로젝트에는 form을 자주 사용하는데, form을 다룰 때 사용하면 좋은 라이브러리 중 React-Hook-Form을 도입해보고자 한다.

✅ React-Hook-Form

공식 사이트에서는 이렇게 소개한다!

React-Hook-Form은 성능이 우수하고 유연하며 쉬운 유효성 검사를 통한 확장 가능한 폼입니다.

그럼 일단 설치하고 시작해보자!😎

1
yarn add react-hook-form

✅ 간단한 예제 살펴보기

아래 예제를 하나씩 살펴보며 각각 무슨 역할을 하는지 알아보자!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
"use client"
import { useForm } from "react-hook-form"

type FormValues = {
  firstName: string
  lastName: string
}

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
    watch,
  } = useForm<FormValues>({
    defaultValues: {
      firstName: "",
      lastName: "",
    },
  })

  console.log(watch("firstName"))
  let firstName = watch("firstName")
  let lastName = watch("lastName")

  const onSubmit = (data) => {
    console.log(data)
  }

  return (
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input {...register("firstName", { required: true })} />
        <p>{errors.firstName && "필수값 입니다"}</p>

        <input {...register("lastName", { required: true, minLength: 4 })} />
        <p>{errors.lastName && "필수값 입니다. 2글자 이상 입력해주세요."}</p>

        <p> 이름은 : {lastName + firstName}</p>

        <button type="submit">등록</button>
      </form>
    </div>
  )
}

➡️ useForm과 타입지정

next.js에서 사용시 use client를 상단에 작성해주고, useForm을 불러온다.

Typescript에서는 아래와 같이 다루게 될 폼의 타입을 지정해 useForm에 적용해주면 된다.

1
2
3
4
5
6
7
"use client"
import { useForm } from "react-hook-form"

type FormValues = {
  firstName: string
  lastName: string
}

➡️ useForm 사용하기

이제 useForm 안에서 필요한 내용을 구조 분해 해준다. 아래에 사용 된 값들은 다음과 같다.

useForm의 속성들역할
registerinput 필드 등록
handleSubmit폼 제출 이벤트 처리
formState폼 상태 관리
watch입력 필드 값 변경 확인

여기에 추가적으로, defaultValues로 각 input값을의 기본값을 지정해줄 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
    watch,
  } = useForm<FormValues>({
    defaultValues: { 👈
      firstName: "",
      lastName: "",
    },
  })

  return(
    //생략
  )
}

➡️ register

React-Hook-Form 기본 정보를 등록하는 과정이다. 아래 예제에서 "firstName" 은 name 속성으로 이용되며, 옆의 required는 이 input의 규칙을 지정하는 역할을 한다.

1
<input {...register("firstName", { required: true })} />

➡️ handleSubmit

form 제출 이벤트를 처리한다. 일반적으로 form 이벤트를 처리할 때 e.preventDefault()를 사용하는데, handleSubmit은 기본적으로 이 내용을 포함하기에 따로 적어주지 않아도 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const onSubmit = (data) => { 👈
  console.log(data)
}

return (
  <div>
    <form onSubmit={handleSubmit(onSubmit)}👈>
      <input {...register("firstName", { required: true })} />
      <p>{errors.firstName && "필수값 입니다"}</p>

      <button type="submit">등록</button>
    </form>
  </div>
)

➡️ formState

아래 예제에서 firstName input은 required:true 조건을 주었다. 만약 사용자가 이 값을 채우지 않고 submit을 시도하면, <p>{errors.firstName && "필수값 입니다"}</p> 가 표시되며, 사용자에게 정보를 알릴 수 있다.

즉 formState는 폼 상태관리에 사용되며, 여기에서 errors값을 이용해, 유효성검사를 통과하지 못했을 경우, 사용자에게 올바른 값 작성을 유도할 수 있다.

1
2
3
4
5
<form onSubmit={handleSubmit(onSubmit)}>
  <input {...register("firstName", { required: true })} />
  <p>{errors.firstName && "필수값 입니다"}</p>👈
  <button type="submit">등록</button>
</form>

➡️ watch

watch를 적용하면, 해당 input 값이 변경되는 걸 실시간으로 확인할 수 있다. 변수에 할당하면, input 값이 변경 될때마다 변수에 새로운 값이 할당 된다.

1
2
3
4
let firstName = watch("firstName")
let lastName = watch("lastName")

console.log(watch("firstName"))

✅ 규칙

React-Hook-Form을 사용해서 아래와 같은 규칙을 쉽게 사용할 수 있다.

규칙의미
required필수 입력
min숫자 필드의 최솟값
max숫자 필드의 최댓값
minLength문자 필드의 최소 길이
maxLength문자 필드의 최대 길이
pattern정규식 패턴과 일치한지 확인
validate사용자 정의 유효성 검사 함수 지정

➡️ required

해당 값이 반드시 필수 임을 지정한다.

1
2
3
4
5
<form onSubmit={handleSubmit}>
  <input {...register("firstName", { required: true })} /> 👈
  <p>{errors.firstName && "필수값 입니다"}</p>
  <button type="submit">등록</button>
</form>

➡️ minLength

문자 필드의 최소 길이를 결정한다. 예제에서는 2를 주었으므로, 2글자 이상 입력해야 하며 규칙을 만족하지 않을 경우 필수값 입니다. 2글자 이상 입력해주세요.가 표시된다.

1
2
3
4
5
<form onSubmit={handleSubmit}>
  <input {...register("lastName", { required: true, minLength: 2 })} /> 👈
  <p>{errors.lastName && "필수값 입니다. 2글자 이상 입력해주세요."}</p>
  <button type="submit">등록</button>
</form>

➡️ pattern

정규식 패턴을 지정해 값을 검사할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
<form onSubmit={handleSubmit}>
  <input
    type="text"
    placeholder="이메일 주소"
    {...register("email", {
      required: true,
      pattern: [원하는 정규식 입력], 👈
    })}
  />
  {errors.email && <p>올바른 이메일 주소를 입력하세요.</p>}
  <button type="submit">등록</button>
</form>

➡️ validate

사용자 정의 유효성 검사 함수를 만들어 지정할 수 있다. 만약 이미지 파일을 업로드하는데, png,와 jpg로 확장자를 제한하고 싶다면, 아래와 같이 파일을 확인할 수 있다. 이때 return 값은 <p>{errors.file.message}</p> 를 표시하는데 사용된다.

참고로 File을 다룰 경우 Type은 FileList를 지정해주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const checkFileType = (value: FileList) => { 👈
  if (value.length === 0) {
    return "파일을 업로드해주세요!"; //errors.file.message 에 출력
  }

  // 확장자 확인
  const correctFormat = ["image/png", "image/jpg"]; //허용 파일 타입
  const file = value[0];
  const fileExtension = file.type.toLowerCase(); //파일 타입

  if (!correctFormat.includes(fileExtension)) {
    return "올바른 파일 형식이 아닙니다!"; //errors.file.message 에 출력
  }

  return true;
};

//생략//
return (
  <form onSubmit={handleSubmit}>
    <input
      type="file"
      {...register("file", {
        required: true,
        validate: checkFileType, 👈
      })}
    />
    {errors.file && <p>{errors.file.message}</p>}
  </form>
)

📩마무리

form을 다룰 때 자주 사용하는 라이브러리인 만큼 이번 프로젝트에 적용해보면서, 적응해보면 좋을 것 같다.❤️‍🔥

🗂️참고 사이트

This post is licensed under CC BY 4.0 by the author.