TypeScript와 React로 개발하면서 setState를 props
로 전달하는 도중 잘못된 타입을 정의해서 발생한 에러이다.
나는 setState를 자식컴포넌트로 props
로 전달하면서 다음과 같은 2가지 실수를 저질렀다.
setState
의 타입을 function type
이 아닌 state type
으로 지정함setState
의 매개변수 타입을 지정하지 않음아래에서 하나씩 차근차근 해결해보겠다.
우선 useState훅을 이용한 state들을 props 전송하는 방법을 간단하게 알아보자.
/* 부모컴포넌트 */
//1. useState 사용 시 state의 type 지정
let [isLoading, setIsLoading] = useState<boolen>(true);
function 부모컴포넌트(){
return (
<>
(중략)
//2. 자식컴포넌트로 전달 (기본 React와 동일)
<자식컴포넌트 isLoading={isLoading} setIsLoading={setIsLoading} />
</>
)
}
useState
옆의 <type>
은 useState
의 state
타입을 지정하는 방법이다.
isLoading
값은 true / false
로, boolean
타입이므로 <boolean>
으로 지정했고,
이 외에도 string, number, boolean
등 지정할 수 있다.
/* 자식컴포넌트 */
interface Props { //3. 부모컴포넌트에서 받아오는 모----든 state들의 type 지정이 필수!
isLoading :boolean; //4. state 타입지정
setIsLoading :(x:boolean)=>void; //5. setState 타입지정 (매개변수도 지정해야 함)
}
function 자식컴포넌트(props :Props){
(중략)
}
위와 같이 자식컴포넌트는 부모컴포넌트로 받아오는 모든 props
에 대한 타입을 필수로 지정해야 한다.
전달받을 props
가 많고, 한 번에 타입지정을 해주고 싶으면 위와 같이 interface
로 묶어서 지정할 수 있다.
사실 정확히 말하면 에러메세지로 스포당했듯, React.Dispatch<React.SetStateAction<type>>
이다.
하지만 위 예제에서 확인했듯, setState는 함수로도 인정이 되기 때문에 ()=>{}
타입을 사용할 수도 있다.
아무튼 나는 state가 아닌 setState를 state type
으로 지정해서 에러메세지를 띄우게 됐다.
/* Navigation.tsx :: 부모컴포넌트 */
let [isSubmenuOpen, setIsSubmenuOpen] = useState<boolean>(false);
function Navigation(){
return(
<>
(중략)
{ isSubmenuOpen && <Submenu setIsSubmenuOpen={setIsSubmenuOpen}/> }
</>
)
}
/* Submenu.tsx :: 자식컴포넌트 */
interface SubmenuProps {
setIsSubmenuOpen: boolean; //※이게 문제
}
function Submenu(props :SubmenuProps){
(중략)
}
/* Submenu.tsx :: 자식컴포넌트 */
interface SubmenuProps {
setIsSubmenuOpen: ()=>void; //1. function type으로 지정해보기
//setState는 return type이 없고 state의 변경을 목적으로 사용하니까 return type을 void로 설정했다.
}
function Submenu(props :SubmenuProps){
(중략)
}
결과는...
똑같은 에러에 지정타입만 변경되었다. ('boolean' > '()=>void')
이 에러를 다시 만나고 내 코드를 다시 차근차근 읽어보니,
setState를 함수로 지정했는데 매개변수타입을 지정해주지 않은 것을 발견했다.
/* Submenu.tsx :: 자식컴포넌트 */
interface SubmenuProps {
setIsSubmenuOpen: (x:boolean)=>void; //2. 매개변수타입을 지정해줬다.
//부모컴포넌트에서 state type을 지정할 때 boolean으로 지정했으니 얘도 당연히 boolean이다.
}
function Submenu(props :SubmenuProps){
(중략)
}
이렇게 setState를 function type
으로 지정해줘도 아무 에러가 발생하진 않지만,
공식문서에서는 setState에 대한 타입을 React.Dispatch<React.SetStateAction<type>>
로 지정하는 것을 권고하고 있고, 에러메세지도 해당 타입으로 띄워주고 있기 때문에 수정해주는 것이 안전할 것으로 판단된다.
React.Dispatch<React.SetStateAction<type>>
이다./* Submenu.tsx :: 자식컴포넌트 */
interface SubmenuProps {
setIsSubmenuOpen: React.Dispatch<React.SetStateAction<boolean>>;
//3. 디스패치 타입으로 변경해주었다
}
function Submenu(props :SubmenuProps){
(중략)
}
React.Dispatch<React.SetStateAction<type>>
이다.
<generic>
키워드를 통해 state 자체의 type을 지정하기boolean, string, number
등React.Dispatch<React.SetStateAction<type>>