본문 바로가기
나도 공부한다/TypeScript

[typescript] useState로 object의 일부 값만 바꾸고 싶을 때

by 꾸빵이 2024. 5. 5.

상황

  • React + TypeScript 환경
  • 닉네임 변경 기능을 구현하는 중이다.
  • 회원 정보 API의 response를 userDetails에 넣어 사용한다.
  • 변경 버튼 클릭시 API를 호출하고 응답 status가 200인 경우 object중 닉네임만 업데이트 해야한다.

 

문제

object의 일부 값만 수정하는 경우엔 아래와 같이 스프레드 연산자를 사용한다.

const [userDetails, setUserDetails] = useState({})
setUserDetails((prevState) => ({
          ...prevState,
          nickname,
        }))

 

 

그래서 이번에도 똑같이 했는데, 이런 엄청나게 긴 에러가 떴다...

interface UserInfo {
  memberId: number
  email: string
  nickname: string
  profileImg: string
}

const [userDetails, setUserDetails] = useState<UserInfo | null>(null)

setUserDetails((prevState) => ({
          ...prevState,
          nickname,
        }))

 

 

'(prevState: UserInfo | null) => { nickname: string; memberId?: number | undefined; email?: string | undefined; profileImg?: string | undefined; }' 형식의 인수는 'SetStateAction<UserInfo | null>' 형식의 매개 변수에 할당될 수 없습니다.
  '(prevState: UserInfo | null) => { nickname: string; memberId?: number | undefined; email?: string | undefined; profileImg?: string | undefined; }' 형식은 '(prevState: UserInfo | null) => UserInfo | null' 형식에 할당할 수 없습니다.
    호출 시그니처 반환 형식 '{ nickname: string; memberId?: number | undefined; email?: string | undefined; profileImg?: string | undefined; }' 및 'UserInfo | null'이(가) 호환되지 않습니다.
      'memberId'의 형식은 해당 형식 간에 호환되지 않습니다.
        'number | undefined' 형식은 'number' 형식에 할당할 수 없습니다.
          'undefined' 형식은 'number' 형식에 할당할 수 없습니다.

 

 

해결 과정

아직 타입스크립트에 익숙하지 않아서 매개변수로 받는 prevState의 형식을 지정해주면 해결될 것이라고 생각했다. 그런데 원인은 상태의 초기 타입 설정에 있었다. userDetails는 UserInfo일 수도 있고 null일 수도 있다. 따라서 prevState도 null일 수 있는 것이다. 그렇기 때문에 'prevState가 null이 아닐 경우에' 라는 조건을 추가해주면 된다. 만약 null이라면 값을 업데이트 하지 않고 prevState를 그대로 다시 반환한다.

 

 

 

최종 코드

interface UserInfo {
  memberId: number
  email: string
  nickname: string
  profileImg: string
}

const [userDetails, setUserDetails] = useState<UserInfo | null>(null)

setUserDetails((prevState) => {
          if (prevState) {
            return {
              ...prevState,
              nickname,
            }
          }
          return prevState
        })