[React Warning] Can't perform a React state update on an unmounted component

곽태욱·2021년 1월 15일
0

원인

외부 서버로 fetch한 후 결과를 업데이트하는 컴포넌트가 있는데, 이런 저런 이유로 중간에 컴포넌트를 DOM에서 unmount하는 경우 위와 같은 경고가 발생할 수 있다. 당연히 컴포넌트가 DOM에서 언마운트됐기 때문에 존재하지 않는 컴포넌트에 상태를 업데이트할 순 없을 것이다.

function WarningComponent() {
  const [state, setState] = useState()
  
  async function warningFunction() {
    const result = await fetch(...)
                               
    // WarningComponent unmounted
                               
    setState(result) // Warning: Can't perform a React state update...
    ...
  }
}
  

해결

해결하는 방법은 아래와 같다.

  1. useRef를 통해 컴포넌트 마운트 상태를 가지는 reference 변수를 생성한다.
  2. useEffect를 통해 컴포넌트 마운트, 언마운트 시 위 변수 값을 변경한다.
  3. 컴포넌트 상태를 업데이트하기 전에 위 변수 값을 확인한다.
function NoWarningComponent() {
  const [state, setState] = useState()
  const isMounted = useRef(false)
  
  useEffect(() => {
    isMounted.current = true
    return () => isMounted.current = false
  }
  
  async function noWarningFunction() {
    const result = await fetch(...)
                               
    // WarningComponent unmounted
    
    if (isMounted.current) {
      setState(result) // Doesn't execute
    }
  }
}

응용

이를 통해 여러 요청이 이뤄지는 도중 중간에 사용자가 요청을 취소하는 경우, 요청을 수행하는 컴포넌트를 언마운트 하는 방식으로 구현할 수 있다.

(근데 코드가 옆으로 길어지는데.. 좋은 방법이 있으면 알려주세요!)

function NoWarningComponent() {
  const [state, setState] = useState()
  const isMounted = useRef(false)
  
  useEffect(() => {
    isMounted.current = true
    return () => isMounted.current = false
  }
  
  async function noWarningFunction() {
    const result = await fetch(...)
    
    if (isMounted.current) {
      const result2 = await fetch(...)
      
      if (isMounted.current) {
        const result3 = await fetch(...)
        ...
      }
    }
  }
}
profile
이유와 방법을 알려주는 메모장 겸 블로그. 블로그 내용에 대한 토의나 질문은 언제나 환영합니다.

0개의 댓글