[스터디] #7 (투두리스트) - React Hook Form

ch9eri·2022년 10월 6일
1

🔨 기본 세팅

기존에 리액트에서 form을 다룰 때 쓰던 방식

function TodoList() {
    const [toDo,setToDo] = useState("");
    const onChange = (event:React.FormEvent<HTMLInputElement>) => {
        const {
            currentTarget: {value},
        } = event;
        setToDo(value);
    };
    const onSubmit = (event:React.FormEvent<HTMLFormElement>) => {
        event.preventDefault();
        console.log(toDo);
    };
    return (
        <div>
            <form onSubmit={onSubmit}>
                <input onChange={onChange} value={toDo} placeholder="write todo" />
                <button>ADD</button>
            </form>
        </div>
    );
};

cf) typescript는 각각에 맞는 event type 지정해줘야함

ex. `event:React.FormEvent<HTMLInputElement>`

cf) input이 여러개면 onChange함수도 input 개수에 맞게 만들어줘야함

코드의 비효율성 🤮

→ 이 모든 걸 한줄로 만들 수 있는 라이브러리 React Hook Form


📌 React Hook Form

사용하기 쉬운 유효성 검사를 통해 성능이 뛰어나고 유연하며 확장 가능한 form

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

🧩 register

const {register} = useForm();

useForm의 register함수를 사용하자

console.log(register("toDo"));

string을 보내주면 name이 된다.

register 함수가 반환하는 모든 것들을 input에 전달한다

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

input 태그 안에 register 함수를 spread해서 넣어줄 수 있다 (ES6 문법)

🧩 watch

form의 입력값의 변화 관찰 함수

input값의 변화를 감지해서 보여준다

<form >
      <input {...register("Email")} placeholder="Email" />
      <input {...register("Name")} placeholder="Name" />
      <input {...register("Id")} placeholder="Id" />
      <input {...register("Pw")} placeholder="Pw" />
      <button>ADD</button>
</form>

이렇게 많은 input값들을 한번에 연결해서 관리할 수 있음 → 효율적!

🧩 handleSubmit

react hook form이 모든 validation을 마쳤을 때만 호출된다

const onValid = (data:any) => {
        console.log(data);
    }

<form onSubmit={handleSubmit(onValid)}>

맨 위의 onSubmit과 같은 기능이다 (하지만 더 간단함!)

🧩 validation

💡 input 필드 필수로 채우기

1. html 태그의 속성으로 적용하기

<input {...register("Email")} required placeholder="Email" />

→ html의 input 속성에 required가 존재하기 때문에 쓸 수 있음

(cf. 지원하지 않는 브라우저에서는 ❌)

2. ✨ 자바스크립트에서 validation 사용하기

<input {...register("Email", {required: true})} placeholder="Email" />

+) {required: true} 를 {}안에 넣은 이유 : 혹시나 .. 사용자가 바꿀 수 있음 ...

required 되지 않은 input창(에러가 있는 항목)으로 커서가 자동으로 옮겨진다

➕) 글자수 유효성 검사

<input {...register("Email", {required: true, minLength: 5})} placeholder="Email" /><input {...register("Email", {required: true})} placeholder="Email" />

🧩 formState

validation과 에러 표시

💡 정규식(RegExp)을 사용한 validation

https://www.regexpal.com

^ 문장의 시작
+ 하나 또는 하나이상
/^[A-Za-z0-9._%+-]+@naver.com$/
/^[A-Za-z0-9._%+-]+@naver.com/g

{...register('Email', {
            required: 'true',
            pattern: /^[A-Za-z0-9._%+-]+@naver.com$/,
{...register('Email', {
            required: 'true',
            pattern: {
              value: /^[A-Za-z0-9._%+-]+@naver.com$/,
              message: 'Only naver.com allowed',
            },
          })}

두가지 방식 모두 가능

💡 formState: {error} - error message 사용자에게 표시

const { register, handleSubmit, formState:{errors} } = useForm();
<span>{errors?.Email?.message}</span>

? : undefined여도 실행하기 (not required)

interface IForm {
  Email: string;
  Name: string;
  Id: string;
  Pw: string;
}

-> interface 작성

formState: { errors },
  } = useForm<IForm>({
    defaultValues: {
      Email: '@naver.com',
    },

-> defaultValues : 타입 지정 및 기본값 설정

💡 +) validation 추가 검사 (custom Validation)

const onValid = (data: IForm) => {
    if(data.Pw !== data.PwConfirm){
        setError("Pw", {message: "Passwords are not same"})
    }
  };

-> 비밀번호 일치 확인

interface IForm {
  Email: string;
  Name: string;
  Id: string;
  Pw: string;
  PwConfirm: string;
  extraError?: string;
}

-> 전체 form에 대한 error

const onValid = (data: IForm) => {
    if(data.Pw !== data.PwConfirm){
        setError("Pw", {message: "Passwords are not same"})
    }
    setError("extraError", {message: "Server offline"})
  };

setError("extraError", {message: "Server offline"})

<span>{errors?.extraError?.message}</span>

-> 사용자에게 표시

{shouldFocus: true}

-> 에러 뜬 곳으로 커서 이동

profile
잘하자!

0개의 댓글