02-07 07:51
Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
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
Archives
관리 메뉴

기록을 합시다.

[React] react-hook-form과 hookform/error-message 이용하여 비밀번호 변경 form 만들기 본문

공부/javascript

[React] react-hook-form과 hookform/error-message 이용하여 비밀번호 변경 form 만들기

울집고양이세마리 2023. 4. 14. 23:53

form을 만들다가, 역시 이것도 내가 하기 귀찮으니 사람들이 만들어준 문명의 이기 중에 하나인 react-hook-form을 이용하기로 했다. 자, 일단은 react-hook-form을 깔아주자. 

npm install react-hook-form

이 포스트에서는 react-hook-form중에서 사람들이 제일 자주 쓰고 유명한 useForm을 위주로 이야기하겠다. 

 

 

useForm

Performant, flexible and extensible forms with easy-to-use validation.

react-hook-form.com

useForm의 props들은 form의 기본 세팅을 해주는 것 위주이다. (지금은 쓸 게 없음..)

 

우리는 useForm의 return props 중에 register를 이용하여 input 값을 validate 할 것이다. 

 

useForm - register

Performant, flexible and extensible forms with easy-to-use validation.

react-hook-form.com

일단은 우리가 써야 하는 register가 있다. 

register는 input 값 혹은 select 값을 등록할 때(submit 할 때), validation을 수행해준다. 

 

아래의 이 코드는 그 예시이다. 

  const passwordRegister = register("password", {
    required: { value: true, message: "현재 비밀번호를 입력하세요. " },
  });

  const newPasswordRegister = register("newPassword", {
    required: { value: true, message: "새 비밀번호를 입력하세요. " },
    validate: (value, formValues) => {
        return (
          value != formValues.password || "현재와 다른 비밀번호를 사용하세요."
        );
      },
  });

  const newPasswordCheckRegister = register("newPasswordCheck", {
    validate: (value, formValues) => {
      return value === formValues.newPassword || "새 비밀번호가 틀립니다.";
    },
  });

register(input에 설정할 id, register 옵션)으로 두 개의 파라미터를 받는다. 

register option으로는 위의 코드처럼 validate도 있고, required도 있고 상황에 맞게 문서를 보면서 사용하면 된다. 

 

아래는 주요하게 쓰이는 option들을 가져와봤다. 

 

1. required option(빈칸을 submit 하면 안 될 때 이용)

<input
  {...register("test"//input id 적는 곳, 굳이 input에 id='test'라고 적을 필요 없다., {
    required: {
		value: true //true로 설정하면 submit 하기 전에 input에 value가 있어야 한다는 뜻
		message: '에러메시지 적는 곳' //value를 true로 설정했을 경우, value가 없을 때 띄울 에러메시지
    }
  })}
/>

 

2. pattern option(보통 이메일 형식 확인할 때 이용)

<input
  {...register("test", {
    pattern: {
      value: /[A-Za-z]{3}/, //정규식 패턴 적는 곳
      message: 'error message' //정규식 패턴에 해당하지 않는다면 뜰 에러 메시지  
    }
  })}
/>

 

3. validate option(회원 가입 할 때, 비밀번호 두 번 써서 확인하거나 할 때 쓰면 유용한듯)

<input
  {...register("test", {
    validate: value => value === '1' || 'error message' //왼쪽 식이 true가 아니라면 오른쪽의 error message 반환 
  })}
/>

 

이렇게 세 개가 자주 쓰이는 듯 하다. 그리고 이것들 외에도 좋아보이는 option들이 꽤 있다.

궁금하신 분들은 문서에 들어가서 보면 될 듯 하다. 예제도 쉽게 설명되어 있어서 바로 사용하기가 쉽다. 

 

return (<input
  {...register("test", {
    validate: value => value === '1' || 'error message' //왼쪽 식이 true가 아니라면 오른쪽의 error message 반환 
  })}
/>);
const testRegister = register("test", {
    validate: value => value === '1' || 'error message' //왼쪽 식이 true가 아니라면 오른쪽의 error message 반환 
  });

return (<input
  {...testRegister}
/>);

참고로 위와 아래 코드의 결괏값은 똑같다. 옵션들을 리턴문에 다 써주면 읽기 힘들어서 아래와 같은 방법을 사용하는 게 내 기준으로 읽기 편했다.

 

그러면 이제 register를 통해 validation을 어떻게 사용하는지 알게 되었다. 

그러면 validateion을 수행하고 나온 error들은 어떻게 처리할까? 

이 때는 hookform/error-message을 사용해준다. 

 

npm install @hookform/error-message

 

 

useFormState - ErrorMessage

Performant, flexible and extensible forms with easy-to-use validation.

react-hook-form.com

이것도 문서를 보면 매우 EZ 하다. 

아래는 문서에서 제공하는 예제를 조금 수정했다. 

 

설명은 주석으로 달아놨다. 

import React from "react";
import { useForm } from "react-hook-form";
import { ErrorMessage } from '@hookform/error-message';

export default function App() {
  //useForm의 return props들을 가져와준다. 
  const { register, formState: { errors }, handleSubmit } = useForm();
  //onSubmit은 formData를 받은 후에 수행할 동작을 적는다. 
  const onSubmit = data => console.log(data); 

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("singleErrorInput", { required: "This is required." })} />
      
      //errors들을 인자로 받고, 그 중에서 id가 "singleErrorInput"인 곳에서 발생하는 에러 메시지들을 출력해준다. 
      <ErrorMessage
        errors={errors}
        name="singleErrorInput"
        render={({ message }) => <p>{message}</p>}
      />
      
      <input type="submit" />
    </form>
  );
}

참고로 handleSubmit은 onSubmit 함수를 인자로 받아주는데, preventdefault를 자동으로 수행 해주고, error가 발생할 때에는 submit 안 해주는 기능이 있다. 마지막으로 onSubmit에는 data를 받은 후에 어떤 동작을 할지 적으면 된다. (서버에 보낸다던지..) 

 

아래는 이 위의 것들을 다 활용하여 짠 코드이다.

import { Card, Button, Input, Spacer } from "@nextui-org/react";

import { useForm } from "react-hook-form";
import { ErrorMessage } from "@hookform/error-message";

export default function ChangePassword({ handleSeletedMenu }) {
  const {
    register,
    formState: { errors },
    handleSubmit,
  } = useForm();

  const onSubmit = (formValues) => {
    console.log(formValues);
  };

  const passwordRegister = register("password", {
    required: { value: true, message: "현재 비밀번호를 입력하세요. " },
  });

  const newPasswordRegister = register("newPassword", {
    required: { value: true, message: "새 비밀번호를 입력하세요. " },
    validate: (value, formValues) => {
        return (
          value != formValues.password || "현재와 다른 비밀번호를 사용하세요."
        );
      },
  });

  const newPasswordCheckRegister = register("newPasswordCheck", {
    validate: (value, formValues) => {
      return value === formValues.newPassword || "새 비밀번호가 틀립니다.";
    },
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Card.Body>
        <Input.Password
          {...passwordRegister}
          label="현재 비밀번호"
          placeholder="현재 비밀번호 입력"
        />
        <ErrorMessage
          errors={errors}
          name="password"
          render={({ message }) => <h6>{message}</h6>}
        />
        <Spacer />
        <Input.Password
          {...newPasswordRegister}
          label="비밀번호 확인"
          placeholder="비밀번호 확인"
        />
        <ErrorMessage
          errors={errors}
          name="newPassword"
          render={({ message }) => <h6>{message}</h6>}
        />
        <Spacer />
        <Input.Password
          {...newPasswordCheckRegister}
          label="비밀번호 확인"
          placeholder="비밀번호 확인"
        />
        <ErrorMessage
          errors={errors}
          name="newPasswordCheck"
          render={({ message }) => <h6>{message}</h6>}
        />
      </Card.Body>
      <Card.Footer>
        <Button
          color="default"
          auto
          light
          style={{ width: "50%" }}
          onPress={() => handleSeletedMenu("menu")}
        >
          취소
        </Button>
        <Button color="primary" auto type="submit" style={{ width: "50%" }}>
          비밀번호 바꾸기
        </Button>
      </Card.Footer>
      <style jsx>
        {`
          h6 {
            color: red;
            font-size: 14px;
            font-weight: bold;
            margin: 8px;
          }
        `}
      </style>
    </form>
  );
}

 

아래는 화면 출력물이다. 

 

진짜 만드는 거 너무 간단해서 눈물이 나올 지경이다. 

 

Comments