가수면

리액트 훅 폼 (useForm) 본문

React/라이브러리

리액트 훅 폼 (useForm)

니비앙 2023. 1. 3. 09:55

npm install react-hook-form

기본

import React from "react";
import { useForm } from "react-hook-form";
import styled from "styled-components";

const Login = () => {
  const {
    register,					// input창 상태관리
    handleSubmit,				//form 함수
    formState: { errors },			// 유효성 파트
  } = useForm();

  const onSubmit = (data) => console.log(data); // console.log 대신 디스패치 들어가면 됨

  return (
    <TestForm onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label htmlFor="email">이메일</label>
        <input
          className={errors?.email?.type === undefined ? "pass" : "fail"}
          type="email"
          id="email"
          name="email"
          {...register("email", { required: true, pattern: /^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/ })}
          aria-invalid={errors.email ? "true" : "false"}
        ></input>
        {errors?.email?.type && <span role="alert">⚠이메일 형식에 맞지 않습니다.</span>}
      </div>
      <div>
        <label htmlFor="password">비밀번호</label>
        <input
          className={errors?.password?.type === undefined ? "pass" : "fail"}
          type="password"
          id="password"
          name="password"
          {...register("password", { required: true, pattern: /^[a-z0-9_-]{4,16}$/ })}
          aria-invalid={errors?.password ? "true" : "false"}
        ></input>
        {errors?.password && <span role="alert">⚠4~16자 이내로 적어주세요</span>}
      </div>
      <div>
        <button>로그인</button>
        <button type="button">회원가입</button>
      </div>
    </TestForm>
  );
};

const TestForm = styled.form`
  span {
    color: red;
  }
  .pass:focus {
    border: 1px solid green;
    box-shadow: 0 0 5px green;
    outline: none;
    transition: box-shadow 0.4s;
  }
  .fail:focus {
    border: 1px solid red;
    box-shadow: 0 0 5px red;
    outline: none;
    transition: box-shadow 0.4s;
  }
`;

export default Login;

 

에러 메세지 핸들링

function ToDoList() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<IForm>({});
.
.
.
    <input
      {...register("email", {
        required: "Email is required",
        pattern: {
          value: /^[A-Za-z0-9._%+-]+@naver.com$/,
          message: "Only naver.com emails allowed",
        },
      })}
      placeholder="Email"
    />
    <span>{errors?.email?.message}</span>

required가 기본 에러 메세지고 pattern의 message는 유효성 검사 메세지임.

따라서 errors?.email?.message를 찍으면 분기에 따른 message가 출력됨

 

추가

비밀번호 재확인

방법 1) watch를 사용

  const {
    register,
    handleSubmit,
    watch,			// 제출되는 input의 값을 확인
    formState: { errors },
  } = useForm();
  
  <input
      type="password"
      id="PWreconfirmation"
      name="PWreconfirmation"
      placeholder="비밀번호 재입력"
      {...register("PWreconfirmation", {
        required: true,
        validate: (value) => value === watch("newPW"),
      })}
      aria-invalid={errors?.PWreconfirmation ? "true" : "false"}
    />
    {errors?.PWreconfirmation && <span role="alert">두 비밀번호가 달라요. 다시 한 번 확인해주세요.</span>}

방법 2) setError를 사용

function ToDoList() {
  const {
    register,
    handleSubmit,
    formState: { errors },
    setError,
  } = useForm<IForm>({});
  const onValid = (data: IForm) => {
    if (data.password !== data.password1) {
      setError(
        "password1",
        { message: "Password are not the same" },
        { shouldFocus: true }
      );
    }

 

글자 포함

    <input
      {...register("firstName", {
        required: "write here",
        validate: {
          noNico: (value) =>
            value.includes("nico") ? "no nicos allowed" : true,
          noNick: (value) =>
            value.includes("nick") ? "no nick allowed" : true,
        },
      })}
      placeholder="First Name"
    />
    <span>{errors?.firstName?.message}</span>

 

제출 시 input 초기화

  const { register, handleSubmit, setValue } = useForm<ITodo>();
  const addTodo = (data: ITodo) => {
    console.log(data);
    setValue("todo", "");
  };
Comments