[Tistory] react-hook-form에서 useController사용하기(feat.제네릭)

원글 페이지 : 바로가기

들어가며 프로젝트를 진행하다 보니 이제는 기본적인 UI작업을 끝내고 실질적인 기능구현이 필요한 차례가 되었다. 가장 기본적으로 로그인을 구현해야 하는데 폼 요소를 컨트롤 하는 것에서 막히고 말았다. React에서는 사용자 입력값을 관리하기 위해서 useState를 줄줄이 만들어야 하기 때문에 이전에 써본 react-hook-form을 냅다 설치하긴 했는데 지금 프로젝트에는 MUI와 TypeScript를 사용하고 있고 TextField를 스타일링 해서 공통 컴포넌트로 빼버렸기 때문에 Props로 어떻게 주고 받을지,,, 특히 MUI에서 제공하는 Props가 있고 react-hook-form을 쓰면 거기서 필요한 Props가 있을텐데 이걸 어떻게 관리해야 좋을지 고민이 많이 되었다. 그러다가 정말 친절한 포스팅을 발견해서 원하는대로 동작하도록 코드를 수정하긴 했지만 완전히 이해하기 위해서 포스트를 따로 작성한다. Type 정보 우선 TypeScript를 사용하기 때문에 react-hook-form의 Type 정보가 필요한데 그건 공식문서에서 제공을 하고 있다. UseController~ 부분을 참고했다. https://react-hook-form.com/ts#UseControllerReturn Typescript Support Performant, flexible and extensible forms with easy-to-use validation. react-hook-form.com Generics Type 정보를 이해하기 위해서는 제네릭에 대한 이해가 선행되어야 한다. 제네릭이란 타입을 함수의 파라미터처럼 사용하는 것을 의미 한다. 특히 함수의 파라미터나 반환 값으로 여러가지 타입을 허용하고 싶어서 any를 사용했을 때 발생하는 타입 문제(any는 타입 검사를 하지 않음)를 해결해 주는 것이 제네릭이라고 보면 된다. 기본적인 사용법은 아래와 같다. // 제네릭으로 사용한 함수
function logText(text: T): T {
return text;
}

// 호출 방법1 – 타입 명시
const text = logText(“hello”);

// 호출 방법2 – 타입 추론
const text = logText(“hello”); 아래는 실제 코드에서 사용된 제네릭이다. // 필요한 type을 import 해옴
import {
useController,
FieldValues,
FieldPath,
UseControllerProps,
} from “react-hook-form”;
import { TextFieldProps } from “@mui/material”;

interface MuiProps {
textFieldProps?: TextFieldProps;
}

const CommonTextField = < TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath,
>({ textFieldProps, …props}: MuiProps & UseControllerProps) => {

} extends 키워드를 사용하여 제약을 걸어주었다. 여기서 사용된 TFieldValues는 FieldValues에 맞는 값만 허용 한다는 것이다. (표현이 맞는지 잘 모르겠다ㅠ) 꺽쇠 안에 들어간 제네릭은 공식문서에서 제공 하는 것과 동일하다. 그리고 MuiProps는 MUI에서 제공하는 TextFieldProps를 가지고 와서 타입을 지정해주었고 & 연산자(Intersection)를 사용해서 UseControllerProps와 합쳐 하나의 타입(interface)으로 만들어 주었다.(모든 타입을 합쳐 놓은 것, 합집합) useController or 기본적으로 MUI와 react-hook-form의 컴포넌트 동작 방식은 동일하지 않다. MUI는 React를 기반으로하는 UI 라이브러리로 제어 컴포넌트(Controlled Component) 방식으로 동작한다. 그 말은 즉 값=상태(State)가 변경될 때 마다 컴포넌트 전체가 리랜더링 된다는 뜻이다. 반면에 react-hook-form은 비제어 컴포넌트(Uncontrolled component) 방식으로 동작하는데 상태(State)를 사용하지 않고 ref를 통해 직접 DOM요소에 접근하여 값을 가져오거나 설정한다. 컴포넌트 전체가 리랜더링되는 것이 아니라 변경된 필드만 다시 렌더링 하여 최적화된 성능을 제공한다. 그렇기 때문에 이 둘을 같이 사용하기 위해서는 react-hook-form에서 제공하는 Controller를 사용해야 한다. Controller를 사용하면 react-hook-form의 장점인 최적화된 성능을 취할 수 있다. Controller를 사용하려면 useController 훅을 사용하거나 컴포넌트를 사용하면 된다. 래퍼 컴포넌트를 사용할 때는 인풋 요소를 로 하나하나 감싸주면 되는데 간단한 form을 만들 때는 빠른 방식이나 재사용하기는 어렵다. 동일한 Props와 Methods를 제공하지만 재사용 가능한 컴포넌트를 만들기 위해서는 useController 훅을 사용한다. https://react-hook-form.com/docs/usecontroller useController Performant, flexible and extensible forms with easy-to-use validation. react-hook-form.com 위 코드에 이어서 사용법은 다음과 같다. const { field, fieldState } = useController(props);

return (

); 아래는 부모 컴포넌트에서 사용한 코드이다. interface FormValue {
id: string;
password: string;
}

const LoginPage = () => {
const { control, handleSubmit } = useForm({
defaultValues: {
id: “”,
password: “”,
},
});

// 로그인 버튼 함수
const handleLogin = (data: FormValue) => {
console.log(data);
};




일단 단순히 값을 받아오는 것 까지만 이해를 했고 기타 제공되는 Props와 Return값에 대해서는 추가로 공부가 필요하다. 기본적인 validation을 구현하면서 알아보면 될 것 같다. 어렵구리😂 Reference 정말 도움이 많이 된 포스팅 두개,,, 감사합니다! https://velog.io/@boyeon_jeong/React-Hook-Form-Controller-useController-y6v2mfc9 [React Hook Form] mui와 같이 사용하기 | Controller, useController 제어 컴포넌트(https://legacy.reactjs.org/docs/forms.htmlReact에서 제어 컴포넌트는 폼 요소뿐만 아니라 일반적인 컴포넌트에서도 사용될 수 있습니다. 그러나 폼 요소를 제어 컴포넌트로 사용하는 것이 velog.io https://velog.io/@syoo970/react-hook-form%EA%B3%BC-MUI%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%9E%AC%EC%82%AC%EC%9A%A9%EC%84%B1-%EC%9E%88%EB%8A%94-Input-%EA%B3%B5%ED%86%B5-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0TypeScript react-hook-form과 MUI를 사용한 재사용성 있는 Input 공통 컴포넌트 만들기(TypeScript) MUI와 react-hook-form을 기반으로 공통 컴포넌트를 만드는 작업이 생각보다 간단하지 않았다. 🤔 그래서 해당 사항을 정리 해보고자 한다.react-hook-form을 사용 해보았다면 사실 가장 처음 사용하게 velog.io https://joshua1988.github.io/ts/guide/generics.html#%EC%A0%9C%EB%84%A4%EB%A6%AD-generics-%EC%9D%98-%EC%82%AC%EC%A0%84%EC%A0%81-%EC%A0%95%EC%9D%98 제네릭 | 타입스크립트 핸드북 제네릭(Generics)의 사전적 정의 제네릭은 C#, Java 등의 언어에서 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징입니다. 특히, 한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를 joshua1988.github.io https://www.typescriptlang.org/ko/docs/handbook/2/generics.html Documentation – Generics Types which take parameters www.typescriptlang.org

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다