[React] 리액트 form 태그 라이브러리 사용하여 회원가입 구현 react-hook-form 사용하기

728x90

회원가입 기능을 구현하려고 했을 때 form 태그를 사용하면 필요한 데이터, 사용자가 입력한 데이터만 쏙쏙 빼서 데이터를 정제하고 서버로 전달할 수 있습니다. 매우 편리한 태그입니다. 이 태그를 react에 맞춰진 라이브러리를 찾아보다가 react-hook-form을 찾게 되었습니다.

React Hook Form이라고 해서 React에서 자체 지원해주는 hook인줄 알았는데 아니에요. react-hook-form이라는 라이브러리를 install 해서 사용하는 겁니다. React의 장점 중 하나는 라이브러리의 세계가 넓습니다.

 

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

 

Get Started

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

react-hook-form.com

 

 

React Hook Form 라이브러리 설치

npm install react-hook-form

위와 같이 설치해줍니다.

 

 

React Hook Form 사용법 - 기본 

doc에 있는 튜토리얼을 보고 따라서 작성했습니다.

doc에 영상도 함께 첨부되어 있어서 보기 편했습니다. 만약 자세하게 알아보고 사용해보고 싶으신 분들은 사이트 내용 확인해보시면 될 것 같습니다.

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

interface SignForm {
    name: string;
    email: string;
    password: string;
}

function SignUp() {
    // react-hook-form 사용 함수
    // register : 등록
    // handleSubmit : submit을 클릭하는 함수
    // watch : 실시간 변화하는 값 확인 함수
    // formState : form 내 데이터 값 상태 확인
    const { register, handleSubmit, watch, formState: { errors } } = useForm<SignForm>();
    
    // submit 클릭시 실행 함수 onSubmit
    const onSubmit: SubmitHandler<SignForm> = (data) => console.log(data)

    // 실시간 확인하는 함수 watch
    const name = watch("name");


    return (
        <form onSubmit={handleSubmit(onSubmit)}>
            <input id="name" placeholder="Name" 
                {...register("name", { 
                    required: "This is required.", 
                    minLength: { value: 2, message: "Min Length is 2" } 
                })}
            />
            <p> {errors.name?.message}</p>
            <p> {name}</p>
        </form>
    );
}

export default SignUp;

이렇게 작성하는 코드가 기본적으로 사용하는 react-hook-form입니다.

여기에서 UI를 더 예쁘게 사용하려면 라이브러리를 사용하면 됩니다. react-hook-form은 외부 UI 구성 요소 라이브러리와 쉽게 통합할 수 있습니다. 구성요소가 입력 참조를 노출하지 않는 경우에는 등록 프로세스를 처리하는 Controller 구성 요소를 사용해야 합니다.

 

 

React Hook Form 사용법 - UI 라이브러리와 통합(Controller)

https://react-hook-form.com/docs/usecontroller/controller

 

Controller

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

react-hook-form.com

MUI와 통합

https://codesandbox.io/p/sandbox/react-hook-form-v7-controller-5h1q5?file=%2Fsrc%2FMui.js%3A89%2C14

 

https://codesandbox.io/p/sandbox/react-hook-form-v7-controller-5h1q5?file=%2Fsrc%2FMui.js%3A89%2C14

 

codesandbox.io

 

아래 코드는 하단의 참고 블로그의 코드입니다. + 일부 수정

import { TextField } from "@mui/material"
import { useForm, Controller } from "react-hook-form"


type FormValues = {
    ReactDatepicker: string
}


function App() {
    // useForm 데이터 관리
    const { control, handleSubmit } = useForm();
    const handle = (data:any) =>{
    console.log(data)
    }

    return (
        <form onSubmit={handleSubmit(handle)}>
        	<Controller
                control={control}
                name="email"
                defaultValue={''}
                rules={{
                  required: 'Email ID is required',
                  pattern: {
                    value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                    message: 'Invalid email address',
                  },
                  minLength: {
                    value: 6,
                    message: 'Email must be at least 6 characters',
                  },
                }}
                render={({ field: { onChange, onBlur, value, ref }, fieldState:{error} }) => (
                    <TextField
                      label="name2"
                      onChange={onChange} // send value to hook form
                      value={value}
                      error={error !== undefined}
                      helperText={error && error.message}
                    />
                  )}
              />
          </form>
    )
}

 

control : useForm, React Hook Form에 넣는 값

name : 역할

pattern : 유효성 검사

minLength, maxLength : 최소, 최대 길이

render : 컴포넌트

 

 

 

최종 코드

import { useState } from "react";
// react-router-dom components
import { Link } from "react-router-dom";
import { useForm, SubmitHandler, Controller } from "react-hook-form";
import { TextField } from "@mui/material";

// @mui material components
import Card from "@mui/material/Card";
import Checkbox from "@mui/material/Checkbox";
// Soft UI React components
import SoftBox from "components/SoftBox";
import SoftTypography from "components/SoftTypography";
import SoftInput from "components/SoftInput";
import SoftButton from "components/SoftButton";
import BaseLayout from "pages/LayoutContainers/Base";
import Socials from "components/Socials";
import Separator from "components/Separator";
// Images
import curved6 from "assets/images/curved14.jpg";

type FormValues = {
  name: string
  email: string
  password: string
  checkpassword: string
}

function SignUp() {
  const [agreement, setAgremment] = useState(true);

  //react-hook-form
  const { handleSubmit, control } = useForm<FormValues>();

  // 제출 시 실행할 함수
  const onSubmit: SubmitHandler<FormValues> = (data) => {

    if (data.password == data.checkpassword){
      console.log("node api 전송")
    }
  };

  return (
    <BaseLayout
      title="Welcome!"
      description="Use these awesome forms to login or create new account in your project for free."
      image={curved6}
    >
      <Card>
        <SoftBox pt={2} pb={3} px={3}>
          <form onSubmit={handleSubmit(onSubmit)}>
            <SoftBox mb={2}>
              <SoftTypography variant="button" color="text" fontWeight="regular">
                Name
              </SoftTypography>
              <Controller
                control={control}
                name="name"
                rules={{
                  required: 'Name is required',
                  pattern: {
                    value: /^[가-힣a-zA-Z]/,
                    message: ""
                  },
                  minLength: {
                    value: 1,
                    message: 'Name must be at least 1 characters',
                  },
                }}
                render={({ field: { onChange, value, ref }, fieldState: {error} }) => {
                  // console.log("name error : ", error)
                  return (
                  <>
                    <SoftInput
                      id="name"
                      type="text"
                      onChange={onChange} // send value to hook form
                      placeholder="Name" 
                      value={value || ""}
                      ref={ref} // ref 전달
                    />
                    <SoftTypography variant="button" color="red" fontWeight="light">
                      {error?.message}
                    </SoftTypography>
                  </>
                  )}
                }
              />
            </SoftBox>
            <SoftBox mb={2}>
              <SoftTypography variant="button" color="text" fontWeight="regular">
                Email
              </SoftTypography>
              <Controller
                control={control}
                name="email"
                rules={{
                  required: 'Email is required',
                  pattern: {
                    value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                    message: ""
                  },
                  minLength: {
                    value: 3,
                    message: 'Email must be at least 3 characters',
                  },
                }}
                render={({ field: { onChange, value, ref }, fieldState: {error} }) => {
                  // console.log("email error : ", error)
                  return(
                  <>
                    <SoftInput
                      id="email"
                      type="email"
                      onChange={onChange} // send value to hook form
                      placeholder="Email" 
                      value={value || ""}
                      ref={ref} // ref 전달
                    />
                    <SoftTypography variant="button" color="red" fontWeight="light">
                      {error?.message}
                    </SoftTypography>
                  </>
                )}}
              />
            </SoftBox>
            <SoftBox mb={2}>
              <SoftTypography variant="button" color="text" fontWeight="regular">
                Password
              </SoftTypography>
              <Controller
                control={control}
                name="password"
                rules={{
                  required: 'Password is required',
                  pattern: {
                    value: /^[가-힣a-zA-Z]/,
                    message: ""
                  },
                  minLength: {
                    value: 1,
                    message: 'Password must be at least 1 characters',
                  },
                }}
                render={({ field: { onChange, value, ref }, fieldState: {error} }) => {
                  console.log("password error : ", error)
                  return(
                  <>
                    <SoftInput
                      id="password"
                      type="password"
                      onChange={onChange} // send value to hook form
                      placeholder="Password" 
                      value={value || ""}
                      ref={ref} // ref 전달
                    />
                    <SoftTypography variant="button" color="red" fontWeight="light">
                      {error?.message}
                    </SoftTypography>
                  </>
                )}}
              />
            </SoftBox>
            <SoftBox mb={2}>
              <SoftTypography variant="button" color="text" fontWeight="regular">
                Password Check
              </SoftTypography>
              <Controller
                control={control}
                name="checkpassword"
                rules={{
                  required: 'Check password is required',
                  pattern: {
                    value: /^[가-힣a-zA-Z]/,
                    message: ""
                  },
                  minLength: {
                    value: 1,
                    message: 'password must be at least 1 characters',
                  },
                  validate: (value) => (value == control._formValues.password) || "Passwords do not match"
                }}
                
                render={({ field: { onChange, value, ref }, fieldState: {error} }) => {
                  console.log("check password error : ", error, control)
                  return(
                  <>
                    <SoftInput
                      id="checkpassword"
                      type="password"
                      onChange={onChange} // send value to hook form
                      placeholder="Check-password" 
                      value={value || ""}
                      ref={ref} // ref 전달
                    />
                    <SoftTypography variant="button" color="red" fontWeight="light">
                      {error?.message}
                    </SoftTypography>
                  </>
                )}}
              />
            </SoftBox>
            <SoftBox mt={4} mb={1}>
              <SoftButton type="submit" variant="gradient" color="dark" fullWidth >
                sign up
              </SoftButton>
            </SoftBox>
          </form>
            <SoftBox mt={3} textAlign="center">
              <SoftTypography variant="button" color="text" fontWeight="regular">
                Already have an account?&nbsp;
                <SoftTypography
                  component={Link}
                  to="/authentication/sign-in"
                  variant="button"
                  color="black"
                  fontWeight="bold"
                  textGradient
                >
                  Sign in
                </SoftTypography>
              </SoftTypography>
            </SoftBox>
        </SoftBox>
      </Card>
    </BaseLayout>
  );
}

export default SignUp;

이름, 이메일, 비밀번호, 비밀번호확인 4가지로 Controller를 생성하여 정규 표현식을 확인하고 함수에서 로그를 찍을 수 있도록 코드를 작성했습니다. 

  • 이름, 이메일, 비밀번호, 비밀번호확인 Controller 생성
  • 정규표현식
  • validate로 값 확인하는 함수 (비밀번호와 비밀번호 확인 인풋값 비교)

render부분에서 태그를 넣는 부분과 error 메세지를 넣어줬고 rules의 pattern에 정규표현식을 잘못 적어서 애를 먹었네요.. 꼭 정규표현식 제대로 작동 되는지 디버깅해보세요!

여기서 사용되는 SoftButton, SoftInput, SoftTypography 등은 프로토타입으로 button, input, p 태그를 커스텀하는 mui를 사용했습니다. 모두 일반 태그로 변경하시고 type과 name 지정을 잘 해주면 될 것입니다!

 

 

참고

https://react-hook-form.com/docs/usecontroller/controller

 

Controller

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

react-hook-form.com

 

https://velog.io/@boyeon_jeong/React-Hook-Form

 

[React Hook Form] react hook form 기본 예시 따라하기

🕐❗❕❓❔🔅⚠⛔❌⭕✔➕➖✖💣💰📔📖🔗🏆🔥⚡😀😎🤓😭😵😲😨😱😮😪😩❤🧡👀☠React Hook Form은 React 유효성 검사와 폼 관리를 단순화하는 강력한💣 라이브러리입니다. 이 라

velog.io

 

728x90