QueenCards / ProjectAnalysis

플젝뿌셔
1 stars 0 forks source link

[25] 리액트 훅폼을 사용하셨네요. 어디에서 왜 사용했나요? 이점이 뭔가요? #28

Closed hyeyoonS closed 1 month ago

hyeyoonS commented 2 months ago

📎 질문

리액트 훅폼을 사용하셨네요. 어디에서 왜 사용했나요? 이점이 뭔가요?

✏ 구술 답변 키워드

✏ 서술 답변

리액트훅폼이란?

비제어 컴포넌트 방식으로 구현된 폼 관리 라이브러리이다. 폼의 유효성 검사와 폼 상태관리를 간단하고 효율적으로 처리할 수 있다.

리액트 훅폼 어디에 왜 사용하는가?

기존 제어컴포넌트로 폼을 다루기 위해서는 인풋요소 하나마다 state를 선언하고 각각의 핸들링함수와 에러를 위한 state, 유효성 검사함수 등이 전부 각각 존재해야했다. 리액트에서는 state가 변할때 리렌더링이 발생한다. 이런 제어컴포넌트 방식으로 폼을 관리함에 따라, 입력의 내용이나 유효성검사 결과가 바뀜 등에 따라 폼전체에 대한 불필요한 렌더링이 무수히 많이 일어나는 문제가 있었다.

리액트훅폼을 이용해 비제어 컴포넌트 방식으로 폼을 다루면 제어컴포넌트 방식으로 폼을 관리할때에 비해 관리해야할 state수가 크게 감소하여 상태관리를 단순화 할 수 있고 state로 인해 발생하던 전체 리렌더링도 감소하여 성능 최적화를 할 수 있다.

추가로, 만약 리액트훅폼 라이브러리 없이 직접 ref와 useRef를 이용해 비제어 컴포넌트로 폼을 관리하고자 한다면, ref로 참조하고 있는 DOM의 업데이트 타이밍을 알기 어렵거나, DOM의 동시접근이나 동시변경으로 인한 타이밍과 동기화 이슈를 겪을 수 있다. 또한 비제어컴포넌트는 폼 제출 시점에 단 한 번 유효성 검사를 실행하기 때문에 비제어컴포넌트 만으로는 실시간 피드백이 어렵다.

리액트훅폼은 쉽고 짧고 직관적인 API를 가져 쉽게 폼 상태를 관리하고 유효성 검사를 할 수 있다.

olseul commented 1 month ago

나의 프로필에서 프로필 변경과 닉네임 변경을 위해 리액트 훅 폼을 사용했습니다.

사용한 이유 리액트 훅 폼은 폼의 상태를 간편하게 관리할 수 있습니다. 이 훅은 폼 필드의 값을 추적하고, 유효성 검사, 에러 메시지 관리 등을 손쉽게 처리할 수 있도록 도와줍니다.

유효성 검사: 내장된 유효성 검사 기능을 제공하여 폼 필드의 유효성을 쉽게 검사할 수 있습니다. 코드에서 NICKNAME_RULES를 사용하여 닉네임 필드의 유효성 검사를 설정하였고, setError를 통해 커스텀 에러 메시지를 표시합니다.

이점 코드 간결화: 폼 상태 관리와 유효성 검사 로직을 간소화하여 코드가 간결해지고 가독성이 높아집니다. 유연성: useForm 훅을 사용하면 폼의 모든 상태와 이벤트를 완벽하게 제어할 수 있습니다. watch, setValue, handleSubmit 등 다양한 메서드를 제공하여 필요에 맞게 폼을 구성할 수 있습니다.

hyeyoonS commented 1 month ago

🤔 1. 리액트 훅폼이 뭐지?

🧐 엥... 제어 컴포넌트, 비제어 컴포넌트가 뭐야....

//제어 컴포넌트 예시 

import React, { useState } from 'react';

const UseInput = () => {
  const [input, setInput] = useState("");
  const onChangeValue = (e) => {
    setInput(e.target.value);
  };

  return (
    <div>
      <input onChange={onChangeValue} />
    </div>
  );
}

export default UseInput;

//  사용자가 입력한 값과 저장되는 값이 실시간으로 동기화 됩니다.
//   ⇒ 이러한 방법으로 데이터를 전부 받아올 수 있어 유효성 검사에 탁월하지만
//      데이터를 하나하나 다 받아오므로 `비효율적`이거나 `속도가 느릴 수 있는 단점`이 있습니다.
//비제어 컴포넌트 예시
import React, { useRef } from 'react';

const UseRefInput = () => {
  const inputRef = useRef(null);
  const onSubmit = () => {
    console.log(inputRef.current.value);
  };

  return (
    <div>
      <input ref={inputRef} />
      <button type="submit" onClick={onSubmit}>
        로그인
      </button>
    </div>
  );
}

export default UseRefInput;

// ref는 값을 업데이트 하여도 리랜더링 되지 않는 특성이 있습니다. 
// 따라서 입력이 모두 되고 난 후 ref를 통해 `값을 한번에 가져와서` 활용합니다.
// ⇒ state로 값을 관리하지 않기 때문에 값이 바뀔 때마다 리렌더링을 하지 않고 값을 한번에 가져올 수 있는 성능 상의 이점이 있습니다. 

🧐 2. 리액트 훅폼을 사용하지 않고 직접 비제어 컴포넌트를 만들면 어떻게 되지?


🤔 3. 리액트 훅 폼을 왜 쓰지?

React Hook Form은 비제어 컴포넌트의 장점을 살리면서도, 위에서 언급한 동기화와 데이터 유효성 검사의 문제를 보완할 수 있습니다.


🤔 4. 리액트 훅 폼을 어디에 썼지?

1. 반려동물에 대한 정보를 입력하고 전송하는 폼

const { 
    register, 
    handleSubmit, 
    formState: { errors, isValid }, 
    setValue, 
    getValues, 
    watch, 
    clearErrors, 
    setError } = **useForm**<IFormInput>({
      defaultValues: { firstMeet: null, birthday: null, weight: null },
      mode: "onTouched"
});
  1. useForm으로 사용할 속성 설정

useForm 훅을 사용해 폼 상태를 초기화하고, 유효성 검사 모드를 설정했습니다. defaultValues는 폼의 초기 값을 지정하며, mode는 필드가 터치될 때 유효성 검사를 실행하도록 합니다. register, handleSubmit, formState 등 다양한 유틸리티를 제공하여 폼 필드를 등록하고, 제출 핸들러를 설정하며, 폼의 상태와 에러 메시지를 관리할 수 있습니다.

(↓↓↓아래는 사용한 유틸리티에 대한 설명)

  1. register : 유효성 검사
    • 사용자가 입력할 수 있는 필드를 폼에 등록합니다. 각 필드에 유효성 검사 규칙을 적용할 수 있습니다.
{...register("title", {
              required: "제목을 입력해주세요.",
              maxLength: { value: 15, message: "최대 15자까지 작성할 수 있습니다." },

<input
  className={styles.writeInput}
  {...register("petName", {
    ...PET_NAME_RULES,
    validate: {
      petNameVerify: () => {
        if (isPetNameConfirm) return true;
        return "중복확인을 해주세요.";
      },
    },
    onChange: () => setIsPetNameConfirm(false),
  })}
  placeholder={PET_PLACEHOLDER.name}
/>
  1. watch : 필드의 값을 실시간으로 변경 (setState와 비슷한 동작)

    • 특정 필드의 값 변화를 실시간으로 감시합니다. 값이 변경될 때마다 해당 값을 반환합니다.
    • 사용 예시 (1) : 일부 필드의 유효성 검사

    watch("petName") 는 petName 필드의 현재 값을 실시간으로 반환합니다.

    폼 제출은 모든 데이터를 한번에 하지만, 사용자 편의를 위하여 폼을 2개의 섹션으로 나누었습니다.

    첫번째 섹션에서 필수 입력 값이 모두 입력되어야만 다음 섹션으로 넘어갈 수 있도록 구현하기 위해, watch를 이용해서 일부 유효성 검사를 실행했습니다.

  const isSectionValid = watch("petName") && watch("type") && watch("breed") !== "" && isPetNameConfirm;
  const section2 = (
    <>
      {/* 성별 */}
      <label className={styles.label}>성별*</label>
      <GenderSelection register={register} watch={watch} />

      {/* 중성화 여부 */}
      <label className={styles.label}>중성화 여부*</label>
      <NeuteringSelection register={register} watch={watch} />
  1. handleSubmit: 폼 제출 핸들러
    • 폼 제출 시 호출되는 함수입니다. 유효성 검사가 완료된 후에 지정한 콜백 함수를 실행합니다.
    • 예: handleSubmit(onSubmit)onSubmit 함수가 폼 제출 시 호출되도록 합니다.
const onSubmit: SubmitHandler<IFormInput> = async (data) => {
  const request = {
    name: data.petName,
    type: data.type,
    breed: data.breed,
    gender: data.gender,
    isNeutered: data.neutering === "Y" ? true : false,
    birth: data.birthday,
    firstMeetDate: data.firstMeet,
    weight: data.weight,
    registeredNumber: data.registeredNumber === "" ? null : data.registeredNumber,
  };

  const formData = new FormData();
  const blob = new Blob([JSON.stringify(request)], { type: "application/json" });
  formData.append("petRequest", blob);
  formData.append("petImage", data.image);

  const res = await postPet({ formData });
  if (res !== null) {
    queryClient.invalidateQueries({ queryKey: ["pets"] });
    openModalFunc();
  }
};

제출된 데이터를 가공하여 서버에 전송합니다. FormData를 사용해 이미지 파일JSON 데이터를 함께 전송합니다.

(+ 서버 응답에 따라 쿼리 캐시를 무효화하고 openModalFunc()를 실행)

  1. Error
    • setError:
    • 특정 필드에 대해 수동으로 에러를 설정합니다.
    • 예: setError("petName", { type: "manual", message: "중복된 이름입니다." })petName 필드에 수동으로 에러 메시지를 설정합니다.
    • clearErrors:
    • 특정 필드 또는 전체 폼의 에러를 제거합니다.
    • 예: 펫 이름 중복 검사의 결과가 true라면 clearErrors("petName") petName 필드에 있던 에러를 제거합니다.
  const checkPetNameMutation = useMutation({
    mutationFn: (name: string) => checkPetName({ name }),
    onSuccess: (res) => {
      if (!res) return setError("petName", { type: "duplicate", message: PET_ERROR_MESSAGE.nameDuplicate });
      setIsPetNameConfirm(true);
      clearErrors("petName");
    },
  });

깡총이

HaydenDevK commented 1 month ago

react-hook-form이란

Jyophie commented 1 month ago

React-hook-form

React Hook Form은 React에서 폼 상태 및 유효성 검사를 쉽게 관리할 수 있도록 도와주는 라이브러리입니다. 이 라이브러리는 성능 최적화, 유연성, 간편한 사용을 목표로 설계되었습니다. React Hook Form을 사용하면 최소한의 리렌더링과 코드로 복잡한 폼을 구현할 수 있습니다.

주요 기능 및 장점

  1. 간편한 사용: 직관적이고 간단한 API를 제공하여 폼 상태를 관리할 수 있습니다.
  2. 성능 최적화: 입력 필드의 변화가 전체 폼을 리렌더링하지 않도록 설계되어 있습니다. 이를 통해 성능이 최적화됩니다.
  3. 유효성 검사: 클라이언트 측 유효성 검사를 쉽게 설정할 수 있습니다. 기본 HTML5 유효성 검사뿐만 아니라 커스텀 유효성 검사도 지원합니다.
  4. 적은 코드량: 다른 폼 라이브러리에 비해 코드 양이 적어 가독성이 좋고 유지보수가 용이합니다.
  5. 유연성: 다양한 UI 라이브러리와 쉽게 통합할 수 있으며, 제어 컴포넌트와 비제어 컴포넌트 모두를 지원합니다.
wise-Ag commented 1 month ago

React hook form은 비제어 컴포넌트로 입력폼을 관리할 수 있도록하는 라이브러리입니다. 이전에 React의 useState를 사용하여 입력폼을 관리할 수 있었습니다. 리액트가 값을 제어하여 제어 컴포넌트라고 불리는데, 실시간으로 값을 동기화하기 때문에 입력값이 변경될 때마다 리렌더링이 발생하는 특징이 있습니다. 입력폼이 많아지면 불필요하게 렌더링 되는 부분이 늘어나고 유효성검사까지 할 경우 에러 상태를 관리할 state까지 늘어나 유지보수가 어렵습니다.

React hook form을 사용한 이유