-
[Custom Hook] return하는 데이터 타입이 전부 유니온으로 합쳐지는 경우Studying/React 2023. 7. 9. 16:15
문제 발생
Portfolly 프로젝트에서 좋아요 버튼을 위한 useLikeBtn 커스텀 훅을 만들다가, return 하는 데이터 값의 타입이 전부 union으로 합쳐지는 문제가 발생했습니다.
(React + TypeScript)
기억이 안 나서 대충 적어보자면 대략 아래와 같은 커스텀 훅이 있습니다.
const useLikeBtn = (initialValue: boolean) => { const [islike, setIsLike] = useState(initialValue); ... return [value1, value2, value3]; // 각각 타입이 string, number, boolean 이라고 가정 }
커스텀 훅을 다른 코드 파일에서 호출한 다음 리턴값 value1을 받으려 하면, 다음과 같은 에러를 마주합니다.
'string | number | boolean' 형식은 (원래 받아야 할 value1 타입)형식에 할당할 수 없습니다. ts(2322)
원인: as const로 상수화 해야한다.
현재 리턴 형태는 배열입니다. 따라서 return 값의 타입이 (string | number | boolean)[] 형태로 되어있던 것입니다.
그 말은 즉슨 value1, value2, value3를 각각 별도 타입으로 반환받지 못하고, string | number | boolean 세 가지 경우를 모두 가질 수 있는 값으로 받게됩니다.
이를 별개로 나누어 받으려면 타입을 상수화 시켜야 합니다.
상수화란, TypeScript에게 특정 값이 변경되지 않을 것임을 알려주는 것입니다.
객체의 모든 필드를 readonly로 만들고, 배열을 readonly로 만들며, 리터럴 값은 그 값 자체를 하나의 타입으로 추론합니다.
// 상수화 하지 않을 경우 let str = "literal"; // type: string // 상수화 할 경우 let str = "literal" as const; // type: "literal" const arr = ["a", "b"] as const; // type: readonly ["a", "b"] const obj = {name: "alldone"} as const; // type: {readonly name: "alldone"}
이로써 타입 추론이 더욱 정확하게 이뤄지게 됩니다.
해결 방법
return문 끝에 as const 를 붙여주면 됩니다.
return [value1, value2, value3] as const;
그 다음 마우스를 hover 하여 return 값의 타입을 확인하면 아래와 같습니다.
type const = readonly [string, number, boolean]
이렇게 상수화를 하면 리턴 값을 받을 때 value1, value2, value3를 각각의 타입으로 받을 수 있습니다.
더하여: Custom Hook에서 여러개 값을 return하는 방법
위에서 저는 return 값을 배열로 받았습니다.
당시에는 그냥 커스텀 훅을 처음 배울 때 본 예시 코드에서 배열로 쓰길래 쭉 그렇게 써왔는데, 문득 커스텀훅 외에는 객체를 보편적으로 사용하지 않나 싶어 그 차이를 알아봤습니다.
Custom Hook에서 여러개 값을 반환하는 방법에는 두 가지가 있습니다.
- array 형태
- object 형태
코드로 보면 아래와 같습니다. 어떤 경우에 두 가지 중 뭘 사용해야 하는지에 대해 정해진 건 없지만, 두 타입의 장단점을 알아보고 사용하면 좋습니다.
const [one, two] = useNumbers(); const { a, b, c } = useAlphabet();
1. Array로 return하는 경우
const [color, setColor] = useState('Salmon'); const [age, setAge] = useState('5');
아래와 같은 상황에서 array로 return하면 좋습니다.
- 적은 수의 값들을 return하는 경우
- 같은 컴포넌트 내에서 한 번 이상 사용하는 경우
array로 리턴값을 넘겨줄 경우 항목 순서를 반드시 지켜야 한다는 단점이 있습니다. 하지만 object보다 변수를 변경하기 간편해 자유롭게 변수명을 설정해서 사용할 수 있습니다. (커스텀 훅은 아니지만) 가장 대표적으로 useState처럼요.
2. Object로 return 하는 경우
const { value1, value2, value3, value4 } = useCustomHook()
아래와 같은 상황에서 array로 return하면 좋습니다.
- 많은 수의 값들을 return하는 경우
- 한 컴포넌트 내에서 한 번만 사용하는 경우
Object는 배열처럼 순서를 기억할 필요가 없으며, 필요한 항목만 가져올 수 있어서 항목이 많은 경우에 사용하기 편합니다. 하지만 항목을 바꿀 때는 { value: data } 같은 형식으로 인해 배열보다 불편하다는 단점이 있습니다.
이렇게 보니 좋아요 버튼 훅 또한 Object 형식으로 리턴하는게 더 좋겠습니다.
참고 사이트
'Studying > React' 카테고리의 다른 글
React quill Editor + react-hook-form feat.TypeScript (0) 2023.07.11 useQuery GET으로 받은 데이터가 props로 전달되지 않을 경우 (0) 2023.07.10 API 요청 코드 분리하기(일반 함수 vs 커스텀 훅) (0) 2023.07.06 [Storybook] Storybook + Twin.macro 환경 설정 (0) 2023.07.01 twin + styled 동적 할당 시 tw 사용이 불가능한 이유 (0) 2023.07.01