본문 바로가기
웹/React

[React] useEffect cleanup 함수의 참조 문제

by 테크케찰 2021. 6. 17.

얼마 전 React Native를 이용해 작업을 하다가 useEffect에서 cleanup함수를 사용할 때 cleanup함수의 값이 제가 원하는 값을 참조하지 않는 문제가 있었습니다. 

오늘은 이 문제를 살펴볼 예정이고, React로 정리를 해보았습니다.

먼저 아래 코드를 보시죠.

import logo from './logo.svg';
import './App.css';

import {
  useEffect,
  useState
} from 'react';

function App() {

  const [page, setPage]=useState(0);

  return(
    <div>
      {
        page===0?
          <StartPage 
            setPage={param=>setPage(param)}
          />
        :
          <Counter 
            setPage={param=>setPage(param)}
          />
      }
    </div>
  )
  
}

const StartPage=({
  setPage,
})=>{
  return(
    <div>
      <div>시작페이지입니다.</div>
      <button onClick={()=>setPage(1)}>Counter로 가기</button>
    </div>
  )
}

const Counter=({
  setPage,
})=>{
  const [value, setValue]=useState(0);

  useEffect(()=>{
    // alert(value);
    return()=>{
      alert(value);
    }
  }, [])

  return (
    <div>
      <div>
        <div>{value}</div>
        <button onClick={()=>{setValue(value+1)}}>+1</button>
        <button onClick={()=>{setValue(value-1)}}>-1</button>
      </div>
      <button onClick={()=>setPage(0)}>시작 페이지로 가기</button>
    </div>
  );
}

export default App;

간단하게 코드를 작성을 했습니다.

StartPage와 CounterPage가 있는데, StartPage에서 Counter로 이동할 수 있고, Counter에서 StartPage로 이동할 수 있습니다.

Counter에서는 value라는 값을 화면에 나타내는데 +1 버튼을 누르면 value값에 1이 더해지고 -1 버튼을 누르면 value 값에 1이 빼집니다. 

useEffect를 이용해서 카운터가 언마운트될 때 그 값을 표시하도록 구현을 해보았습니다.

이 사진을 보시면 value는 4를 나타내고 있는데 0을 alert하고 있는 것을 확인하실 수 있습니다. 

useEffect에서 cleanup 함수를 쓸 떄 value 값을 초기값인 0으로 참조하고 있어서 이러한 문제가 발생합니다.

 

이러한 문제를 해결하기 위해서는 useRef 훅을 사용하시면 됩니다.

import logo from './logo.svg';
import './App.css';

import {
  useEffect,
  useState,
  useRef,
} from 'react';

function App() {

  const [page, setPage]=useState(0);

  return(
    <div>
      {
        page===0?
          <StartPage 
            setPage={param=>setPage(param)}
          />
        :
          <Counter 
            setPage={param=>setPage(param)}
          />
      }
    </div>
  )
  
}

const StartPage=({
  setPage,
})=>{
  return(
    <div>
      <div>시작페이지입니다.</div>
      <button onClick={()=>setPage(1)}>Counter로 가기</button>
    </div>
  )
}

const Counter=({
  setPage,
})=>{

  const [value, setValue]=useState(0);

  const valueRef=useRef();
  valueRef.current=value;

  useEffect(()=>{
    // alert(value);
    return()=>{
      alert(valueRef.current);
    }
  }, [])

  return (
    <div>
      <div>
        <div>{value}</div>
        <button onClick={()=>{setValue(value+1)}}>+1</button>
        <button onClick={()=>{setValue(value-1)}}>-1</button>
      </div>
      <button onClick={()=>setPage(0)}>시작 페이지로 가기</button>
    </div>
  );
}

export default App;

아래와 같이 코드를 다시 짜보았는데요, valueRef라는 값을 이용해 value란 state를 참조하고 있습니다.

이렇게 코드를 짜니 아래와 같은 결과를 얻을 수 있었습니다.

따라서 useEffect의 cleanUp 함수에서 값을 참조할 때 잘 되지 않으신다면, ref를 이용하시는 걸 추천드립니다.