useOnChange라는 커스텀 훅이 있다. 이 커스텀 훅은 input혹은 textarea와 같은 사용자 입력 컴포넌트의 onChange속성에 할당될 것이다.
코드를 살펴보도록 하자.
import { Dispatch, SetStateAction } from "react";
interface IProps {
setInputValues: Dispatch<SetStateAction<ICommonAuthValues>>;
}
interface IUseOnChange {
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
function useOnChange({ setInputValues }: IProps): IUseOnChange {
const onChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
const { name, value } = e.target;
setInputValues((inputValues) => ({
...inputValues,
[name]: value,
}));
};
return { onChange };
}
export default useOnChange;
setInputValues를 props로 받는 이 커스텀 훅은, onChange함수를 반환한다. 여기에서의 onChange 함수는 ICommonAuthValues라는 인터페이스 타입의 inputValues를 관리하는 기능을 한다.
ICommonAuthValues 인터페이스
interface ICommonAuthValues {
email: string;
password: string;
nickName?: string;
confirmPassword?: string;
}
이 커스텀 훅은 현재 'ICommonAuthValues' 인터페이스에 한정된 inputValues를 props로 받고 있다. 그러나 onChange 함수는 모든 사용자 입력 컴포넌트에 필요하다. 따라서, 재사용성을 높이기 위한 방법을 찾아야만 했다.
이러한 문제를 해결하기 위해, useOnChange 훅을 제네릭을 사용하여 재구성하였다. 제네릭을 활용하면, 훅이 다양한 타입의 상태를 유연하게 처리할 수 있게 된다. 재구성된 훅은 다음과 같다.
import { Dispatch, SetStateAction } from "react";
// IProps 인터페이스를 사용하는 컴포넌트가 전달할 입력 값의 타입을 T로 정의
interface IProps<T> {
// T 타입의 상태를 업데이트
setInputValues: Dispatch<SetStateAction<T>>;
}
interface IUseOnChange {
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
// T 타입은 useOnChange 함수가 반환하는 객체(IUseOnChange) 내의 onChange 함수에서 상태 업데이트에 사용 됨
function useOnChange<T>({ setInputValues }: IProps<T>): IUseOnChange {
const onChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
const { name, value } = e.target;
setInputValues((inputValues) => ({
...inputValues,
[name]: value,
}));
};
return { onChange };
}
export default useOnChange;
이제 useOnChange 커스텀훅을 호출하여 사용하는 곳에서, 제네릭 타입을 명시해주면 된다.
const { onChange } = useOnChange<ISignInValues>({ setInputValues });
const { onChange } = useOnChange<ICreatePostValues>({ setInputValues });
안 된다. any 타입을 사용하면 타입스크립트의 주요 이점 중 하나인 타입 안전성이 손상된다. 타입 체크가 이루어지지 않기 때문에, 런타임에 예상치 못한 오류가 발생할 수 있다. 타입스크립트를 사용하는 이유가 사라지는 것이다.
제네릭 타입
제네릭 타입은 타입스크립트에서 타입의 재사용성을 높이기 위해 사용된다. 제네릭을 사용하면, 함수가 다양한 타입을 처리할 수 있게 되며, 이는 코드의 유연성과 타입 안전성을 동시에 증가시킨다. 제네릭을 사용할 때, 타입스크립트 컴파일러는 타입 정보를 유지하며, 타입 체크를 수행할 수 있다.
any 타입
any 타입은 타입스크립트에서 어떠한 타입도 허용하는 방식이다. any를 사용하면, 당장은 타입 체크를 우회할 수 있으나, 타입 안전성을 크게 저하시키는 결과를 가져온다.
제네릭을 사용함으로써, 커스텀 훅이 다양한 타입의 상태를 처리할 수 있게 되었다. 이는 다양한 컨텍스트와 프로젝트에서 커스텀 훅을 재사용할 수 있게 한다는 것을 의미한다. 예를 들어, 단일 useOnChange 커스텀 훅으로 로그인, 회원가입, 글 포스팅, 댓글 달기 등 다양한 상태를 처리할 수 있다. 이로 인해 중복되는 불필요한 코드양을 줄이고, 효과적으로 확장성과 재사용성을 향상시킬 수 있었다.