react-hook-form

김재현·2022년 3월 26일
0

공식 문서

https://react-hook-form.com/

설치

npm install react-hook-form

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

type Inputs = {
  example: string,
  exampleRequired: string,
  
export default function App() {
  const { register, handleSubmit, watch, formState: { errors } } = useForm<Inputs>();
  
  const onSubmit: SubmitHandler<Inputs> = data => console.log(data);
  // 전체를 관찰하려면 value값을 빼면 된다 watch()
  console.log(watch("example")) 
  
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input defaultValue="test" {...register("example")} />
    // validation을 두번째 파라미터로 추가할 수 있다 
    <input {...register("exampleRequired", { required: true , minLength: 5})} />
      {errors.exampleRequired && <span>This field is required</span>}
      <input type="submit" />
    </form>
  );
}
  • register : 를 input에 넣어서 react-hook-form을 활성화한다.
  • handleSubmit : preventDefault()를 포함하여 form을 submit한다.
  • watch: console.log(watch())를 이용해 데이터를 팔로우하여 손쉽게 확인 가능하다.
  • formState: console.log(formState.errors)로 에러 핸들링과 에러 팔로우가 손쉽게 가능하다.

Error Message

다음과 같이 유효성 검사에 ErrorMessage를 추가할 수 있다.

input {...register("password", { required: {Password is Required} , minLength: {value:5, message:"Your Password is too short"})} />

ErrorMessage를 컴포넌트로 확인하기.
Error가 발생할때 message가 존재하기 때문에 아래처럼 표현 가능하다.

input {...register("password", { required: {Password is Required} , minLength: {value:5, message:"Your Password is too short"})} />
// error가 발생한다면 데이터의 존재 유무를 파악하고 `?`로 해결가능 
<span>{formState.errors.email?.message}<span>                  

정규표현식

유효성 검사로 정규식 표현이 가능하다
ErrorMessage를 포함하기 위해 객체로 표현가능하고 메세지를 포함하지 않을 경우 정규식만 표현하면 된다.

...
	<input {...register("email", { required: true , pattern: {
      value: /^[A-Za-z0-9._%+-]+@naver.com$/,
      message: "Only naver.com emails allowed"
    })} />

https://regex101.com/

추가 기능

setError

setError는 발생하는 문제에 따라 추가적으로 에러를 설정할 수 있게 도와준다.
해당 Error를 활용하여 handleSubmit을 컨트롤하면 비밀번호와 비밀번호 확인 Input을 비교하거나 서버 Error 등 추가적으로 Error를 설정 할 수 있다.
setError()의 마지막 객체로 {shouldFocus: true}객체를 보내주면
에러가 발생한 위치로 커서가 자동으로 이동 된다

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

interface IForm {
  email: string;
  password: string;
  password1: string;
  username: string;
  nickname: string;
}
function ToDoList() {
  const { register, formState, handleSubmit, setError } = useForm<IForm>({
    defaultValues: { email: "@naver.com" },
  });
  
  const onValid = (data: IForm) => {
    if(data.password !== data.password1) {
     setError("password1", {message: "Password are not the same"}, {shouldFocus: true}) 
    }
  };
  
  console.log(formState.errors);
  
  return (
    <div style={{ width: 500, margin: "0 auto" }}>
      <form
        style={{ display: "flex", flexDirection: "column" }}
        onSubmit={handleSubmit(onValid)}
      >
        <input
          {...register("email", {
            required: "Email is required",
            pattern: {
              value: /^[A-Za-z0-9._%+-]+@naver.com$/,
              message: "Only naver.com emails allowed",
            },
          })}
        />
        <span>{formState.errors.email?.message}</span>
        <input
          {...register("password", { required: "Password is required" })}
        />
        <span>{formState.errors.password?.message}</span>
       <input
          {...register("password1", { required: "Password1 is required" })}
        />
        <span>{formState.errors.password1?.message}</span>
        <input
          {...register("username", { required: "Username is required" })}
        />
        <span>{formState.errors.username?.message}</span>
        <input
          {...register("nickname", { required: "NickName is required" })}
        />
        <span>{formState.errors.nickname?.message}</span>
        <button>Add</button>
      </form>
    </div>
  );
}

export default ToDoList;

validate

만약 특정 문자나 상황을 설정하고 싶을때 활용 가능한 옵션이다.
예를 들어 email에 abcd가 포함된 email을 거절하기 위해 다음과 같이
validate 함수를 만들면 된다.
문자열이 return된 경우 에러메세지로 return되고 true를 return하면 유효성검사가 통과된다 반대로 false는 거절된다

<input
          placeholder="Email"
          {...register("email", {
            required: "Email is required",
            pattern: {
              value: /^[A-Za-z0-9._%+-]+@naver.com$/,
              message: "Only naver.com emails allowed",
            },
            validate: (value) =>
              value.includes("abcd") ? "abcd is not passed" : true,
          })}
        />

여러개의 유효성 검사를 추가하기 위해 여러개의 규칙을 객체 형태로 줄수 있다.

async를 사용히여 비동기로 만들어서 서버에 확인하고 응답을 받을 수도 있다.

validate: {
              // noAbcd:async(value) 가능
              noAbcd: (value) =>
                value.includes("abcd") ? "abcd is not passed" : true,
              no1234: (value) =>
                value.includes("1234") ? "1234 is not passed" : true,
            }

setValue

useForm의 setValue를 활용하여 input value를 초기화 해 줄 수 있다.

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

interface IForm {
  input: string;
}
function ToDoList() {
  
  const { register, handleSubmit, setValue } = useForm<IForm>();
  
  const submitHandler = (data: IForm) => {
    console.log(data);
    setValue("input", "")
  };
  return (
    <div>
      <h1>To Dos</h1>
      <hr />
      <form onSubmit={handleSubmit(submitHandler)}>
        <input {...register("input")}></input>
        <button>Add</button>
      </form>
    </div>
  );
}

export default ToDoList;

NextJS에서 활용

component로 나눈 Input의 경우 다른 방식으로 register를 전달해야한다.

Enter.tsx


	interface InputForm {
     email: string;
     phone: string;
    }
	...
    
    const { register } = useForm<InputForm>();

	...
    
    <Input register={register("email"), { required: true, }} label="Email" name="email" required />
    <Input register={register("phone"), { required: true, }} label="Phone" name="phone" required />
      
    ...

components/input.tsx

interface InputProps {
 	 name: string;
 	 label: string;
 	 [key: string]: any;  // 아무 props를 받고 싶을때
}

export default function Input({
  label,
  name,
  register,
  ...rest
}: InputProps)

...

	<input
          id={name}
	      {...register}             // 이미 Enter.tsx에서 실행했기때문에 ()불필요
          {...rest}
          required
        />
...
profile
개발자

0개의 댓글

관련 채용 정보