이번 에러도 이 전 포스팅과 같이 TypeScript와 Redux로 개발하던 중 발생한 에러이다.
다시 한 번 느끼지만 TypeScript는 내가 모르고 지나쳤던 나의 실수들을 바로잡고 더 성장하는 데 큰 도움을 주는 것 같다.
우선 에러가 발생하면 에러내용을 잘 살펴봐야 한다.
setState()
호출을 찾고 수정해라.아래에서 천천히 해결해보자
다행히 나는 컴포넌트 분리 및 리팩토링을 다 해놓은 상태에서 해당 에러를 발견해서 어느 부분에서 해당 에러가 발생했는지 바로 찾을 수 있었다.
나는 setState()
가 아닌, useDispatch
에서 에러가 발생하고 있었다.
(TypeScript로 해당 에러를 발견할 수 있었지만, TypeScript조차 일부 에러는 어디서 에러가 발생했는지는 알려주지 않으므로 에러코드를 놓치기 쉬우니, 프론트엔드 개발자라면 개발자 도구를 수시로 확인하자)
에러코드에서는 setState()
로 명시되어 있었기 때문에, 만약 코드가 긴 상황이었다면 해당 에러 발생지점이 useDispatch
라는 것을 찾는데 시간이 걸렸을 것 같았다.
그리고 useDispatch
또한 Redux 내의 state
를 변경하는 함수이므로 내부적으로는 setState()
사용 또는 그 역할을 하기 때문에 해당 에러가 발생할 수 있다.
import { changePage, pageTitleInterface } from "store/store";
function Shop(){
let dispatch = useDispatch();
let headerInfo: pageTitleInterface = {
page: 'shop',
title: 'iPad 쇼핑하기',
subTitle: '',
}
dispatch(changePage(headerInfo)) //////←에러발생지점
return(
<div id="shop">
//중략...
</div>
)
}
위 코드를 살펴보면 저장소 store.ts에서 changePage
라는 함수를 가져와 dispatch
로 headerInfo
내용을 changePage
의 파라미터로 Shop 컴포넌트를 렌더링 하는동안 전달하고 있는 것을 확인할 수 있다.
👉🏻 여기서 중요한 점은 렌더링 하는 동안 dispatch
로 changePage
를 통해 store.ts에 저장되어있는 어느 한 state
를 변경하고 있다는 것이다.
이 에러에 대해서 알아보니, React GitHub에서도 언급했었고 아래 내용에 대해서도 명시되어 있었다.
- 렌더링하는 동안 setState를 사용하면 안 됩니다.
- 해당 함수 구성 요소는 본질적으로 클래스 구성 요소 렌더링 메서드와 동일합니다.
나는 해당 useDispatch
를 컴포넌트 주기에서 최초 1회만 실행하면 되기 때문에, useDispatch
코드를 useEffect
안으로 넣어주려고 한다.
👉🏻 useEffect 사용법, React의 LifeCycle
*만약 setState()
로 해당 에러를 만났다면 setState()
를 렌더링 이후로 변경해주면 된다.
import { useEffect } from "react"
import { changePage, pageTitleInterface } from "store/store";
function Shop(){
let dispatch = useDispatch();
useEffect(()=>{
let headerInfo: pageTitleInterface = {
page: 'shop',
title: 'iPad 쇼핑하기',
subTitle: '',
}
dispatch(changePage(headerInfo))
},[dispatch])
return(
<div id="shop">
//중략 ..
</div>
)
}
항상 돌이켜보면 뭐든 설계단계가 제일 중요한 것 같다.
이번 에러도 어떻게 보면 설계미스에서 비롯된 에러였고,
React 컴포넌트의 LifeCycle과 state의 불변성 등 고려할 점이 많은 것 같다.
이러한 React의 특성을 잘 고려해서 설계하는 습관을 들이자.
state
는 렌더링 이후 변경하자
특정 상황이 아닌 특정 시점에 state
변경이 필요하다면 useEffect
를 사용하자
특정 상황에 변경해야 한다면 onClick, onMouseLeave
등 함수를 사용하자