[Error/TypeScript] TS2322: Type 'Dispatch<SetStateAction<boolean>>' is not assignable to type 'boolean'. (setState는 'boolean'타입이 아님, React+TypeScript에서 setState props 전달하기)

keynene·2023년 8월 29일
0

세팅/오류 Tips

목록 보기
9/11


TypeScript와 React로 개발하면서 setStateprops로 전달하는 도중 잘못된 타입을 정의해서 발생한 에러이다.
나는 setState를 자식컴포넌트로 props로 전달하면서 다음과 같은 2가지 실수를 저질렀다.

  1. setState의 타입을 function type이 아닌 state type으로 지정함
  2. setState의 매개변수 타입을 지정하지 않음

아래에서 하나씩 차근차근 해결해보겠다.




useState훅의 state를 props 전송 시 타입지정 하는 방법

우선 useState훅을 이용한 state들을 props 전송하는 방법을 간단하게 알아보자.

1. 부모컴포넌트에서 state 타입지정 및 props 전송하기

/* 부모컴포넌트 */
//1. useState 사용 시 state의 type 지정
let [isLoading, setIsLoading] = useState<boolen>(true);

function 부모컴포넌트(){
  return (
  	<>
      (중략)
      //2. 자식컴포넌트로 전달 (기본 React와 동일)
      <자식컴포넌트 isLoading={isLoading} setIsLoading={setIsLoading} />
    </>
  )
}

useState옆의 <type>useStatestate 타입을 지정하는 방법이다.

isLoading값은 true / false로, boolean타입이므로 <boolean>으로 지정했고,
이 외에도 string, number, boolean 등 지정할 수 있다.



2. 자식컴포넌트에서 부모컴포넌트로부터 전달받은 props들 타입지정하기 (interface)

/* 자식컴포넌트 */
interface Props { //3. 부모컴포넌트에서 받아오는 모----든 state들의 type 지정이 필수!
  isLoading :boolean; //4. state 타입지정
  setIsLoading :(x:boolean)=>void;  //5. setState 타입지정 (매개변수도 지정해야 함)
}

function 자식컴포넌트(props :Props){
  (중략)
}

위와 같이 자식컴포넌트는 부모컴포넌트로 받아오는 모든 props에 대한 타입을 필수로 지정해야 한다.
전달받을 props가 많고, 한 번에 타입지정을 해주고 싶으면 위와 같이 interface로 묶어서 지정할 수 있다.

이제 state와 setState의 타입지정하는 방법을 알았으니 에러가 난 이유와 해결방법에 대해 알아보자.




setState는 Function 이다.

사실 정확히 말하면 에러메세지로 스포당했듯, React.Dispatch<React.SetStateAction<type>>이다.
하지만 위 예제에서 확인했듯, setState는 함수로도 인정이 되기 때문에 ()=>{}타입을 사용할 수도 있다.

아무튼 나는 state가 아닌 setState를 state type으로 지정해서 에러메세지를 띄우게 됐다.


부모컴포넌트에서 state 타입지정은 잘했음

/* Navigation.tsx :: 부모컴포넌트 */
let [isSubmenuOpen, setIsSubmenuOpen] = useState<boolean>(false);

function Navigation(){
  return(
    <>
 	  (중략)
      { isSubmenuOpen &&  <Submenu setIsSubmenuOpen={setIsSubmenuOpen}/> }
    </>
  )
}

자식컴포넌트에서 setState의 타입지정을 실수했던게 문제였다.

/* Submenu.tsx :: 자식컴포넌트 */
interface SubmenuProps {
  setIsSubmenuOpen: boolean; //※이게 문제
}

function Submenu(props :SubmenuProps){
  (중략)
}



에러해결시도

에러해결시도1. setState 타입지정을 function type으로 해보기

/* Submenu.tsx :: 자식컴포넌트 */
interface SubmenuProps {
  setIsSubmenuOpen: ()=>void; //1. function type으로 지정해보기
  //setState는 return type이 없고 state의 변경을 목적으로 사용하니까 return type을 void로 설정했다.
}

function Submenu(props :SubmenuProps){
  (중략)
}

결과는...

똑같은 에러에 지정타입만 변경되었다. ('boolean' > '()=>void')

이 에러를 다시 만나고 내 코드를 다시 차근차근 읽어보니,
setState를 함수로 지정했는데 매개변수타입을 지정해주지 않은 것을 발견했다.



에러해결시도2. setState function type의 매개변수 타입도 지정해보기

/* 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>>로 지정하는 것을 권고하고 있고, 에러메세지도 해당 타입으로 띄워주고 있기 때문에 수정해주는 것이 안전할 것으로 판단된다.



결론 : setState의 type은 React.Dispatch<React.SetStateAction<type>>이다.

/* Submenu.tsx :: 자식컴포넌트 */
interface SubmenuProps {
  setIsSubmenuOpen: React.Dispatch<React.SetStateAction<boolean>>; 
  //3. 디스패치 타입으로 변경해주었다
}

function Submenu(props :SubmenuProps){
  (중략)
}



📚 React+TypeScript에서의 setState 타입은?

React.Dispatch<React.SetStateAction<type>>이다.


다시 정리하는 state 타입지정 및 전송하는 방법

  1. 부모컴포넌트에서 <generic>키워드를 통해 state 자체의 type을 지정하기
  2. props 전송은 기존 React와 동일하게 전송하기
  3. 자식컴포넌트에서 부모컴포넌트로부터 받아온 모-든 state들에 대한 type 지정하기 (interface)
  4. state type : boolean, string, number
    setState type : React.Dispatch<React.SetStateAction<type>>
profile
keynene

0개의 댓글

관련 채용 정보