ReactHookForm을 사용한 사용자데이터받기 + 미리보기

정소현·2024년 10월 25일
0

팀프로젝트

목록 보기
27/50

★ React Hook From

우리는 사용자의 정보를 받아 실시간으로 미리보기를 제공하기로 하였다.
reacthookform을 사용하여 구현하기로 하였다.

♧ React Hook Form 사용이유

  • 간결하고 직관적인 코드의 작성
  • 입력값의 변화에 따라 전체 폼을 다시 렌더링 하는 것이 아닌 필요한 입력 요소만 렌더링 한다는 장점
  • 커스텀 템플릿을 만들면서 많고 복잡한 값들을 받아야하는데 복잡한 폼 요소상태들을 관리하는데 편리하다고 느꼈다.
  • React Hook Form은 ref를 이용한 비제어 컴포넌트방식을 이용해 어떠한 값을 입력할 때에 리렌더링의 횟수를 줄여준다.

useState의 사용없이 useForm (control, register) 과 useWatch로 실시간 데이터를 받아 폼의 입력 값이 변경될 때마다 미리보기를 띄우는데 용이했다. 간단한 로직 처리로 빠른 처리를 할 수 있는 점이 장점이었다.

♧ 사용방법

  1. react-hook-form설치
npm install react-hook-form
  1. useForm()으로 register, handleSubmit, useWatch 를 불러온다.
const { register, handleSubmit, usewatch, formState: { errors } } = useForm()
  1. register를 사용하여 각각의 input값들에 연결시킬 키를 연결해준다.
    useWatch로 register에 부여해준 키를 사용하여 실시간 입력값들을 확인할 수 있음
  • usewatch 와 watch의 차이 : usewatch는 변경이 된 부분만 리렌더링 하지만 watch는 모든 부분을 리렌더링 한다. (성능의차이를 줄 수 있음)

☼ 공식문서 예제

import { useForm, SubmitHandler } 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);

  console.log(watch("example")) 

  return (
    /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register("example")} />
      
      {/* include validation with required or other standard HTML validation rules */}
      <input {...register("exampleRequired", { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}
      
      <input type="submit" />
    </form>
  );
}

★ 내 코드 사용예제

신부, 신랑 측 성함을 받고 뒤에 미리보기로 실시간으로 연결을 해주어야했다.
컴포넌트를 분리하여 Input.tsx와 Preview.tsx로 나누었고 Input.tsx에서 값을 입력받고 Preview에서 useWatch()를 사용하여 변경되는 부분을 리렌더링하여 볼 수 있도록 만들어주었다.

const MainPhotoInput = () => {
  const { register } = useFormContext();
  return (
    <div className='flex flex-col justify-center items-center '>
      <div className='flex flex-col gap-2'>
        <h2 className='text-2xl font-bold text-black text-center'>청첩장 대표 사진</h2>
        <div className='flex gap-4'>
          <label>이름</label>
          <input
            type='text'
            placeholder='좌측'
            {...register('mainPhoto_info.leftName')}
            className='h-[32px] w-[92px] pl-[8px] py-[9px] border text-[12px] rounded-[8px]'
          />
          <input
            type='text'
            placeholder='♥︎'
            {...register('mainPhoto_info.icon')}
            className='h-[32px] w-[40px] pl-[8px] py-[9px] border text-[12px] rounded-[8px] placeholder:text-center'
          />
          <input
            type='text'
            placeholder='우측'
            {...register('mainPhoto_info.rightName')}
            className='h-[32px] w-[92px] pl-[8px] py-[9px] border text-[12px] rounded-[8px]'
          />
        </div>
        <div className='flex gap-4 '>
          <label>글꼴</label>
          <div className='grid grid-cols-2 gap-4 '>
            {FONTMENU.map((font) => (
              <button
                key={font.name}
                className='p-1 text-black bg-gray-100 hover:bg-primary300 hover:text-white rounded-md font-bold'
              >
                {font.name}
              </button>
            ))}
          </div>
        </div>
        <div className='flex gap-4'>
          <div>사진영역</div>
          <textarea
            id='IntroduceContent'
            placeholder='메인 화면 문구를 작성해주세요.'
            className='rounded'
            {...register('mainPhotoInfo.introduceContent')}
          ></textarea>
        </div>
      </div>
    </div>
  );
};

export default MainPhotoInput;
const MainPhotoPreView = ({ control }: { control: Control<InvitationFormType> }) => {
  const mainPhotoInfo = useWatch({
    control,
    name: 'mainPhoto_info',
  });

  return (
    <div className='p-4 border rounded-md text-center'>
      <h2 className='text-lg font-bold'>청첩장 대표 사진 미리보기</h2>
      <div className='flex justify-center items-center gap-2 mt-4'>
        <p className='text-xl'>{mainPhotoInfo?.leftName || '좌측 이름'}</p>
        <p className='text-xl'>{mainPhotoInfo?.icon || '♥︎'}</p>
        <p className='text-xl'>{mainPhotoInfo?.rightName || '우측 이름'}</p>
      </div>
    </div>
  );
};

☃︎ React Hook Form을 사용하며...

이전에는 Form을 사용할 때 useState()를 사용하여 상태를 저장하고 불러와야했는데 register로 간편하게 input을 연결하고 key를 통하여 usewatch()로 효율적으로 리렌더링을 불러와 성능적으로도 개선시킬 수 있는 점이 편리하고 좋았다.

0개의 댓글