본문 바로가기
IT/React & Next.js

[React] Clean-up 함수에 대해 (feat. useRef)

by 저당단 2024. 11. 22.

useEffect는 컴포넌트가 렌더링된 직후 실행되는 훅이다.

그리고 보통 컴포넌트가 언마운트될 때 실행할 동작을 설정하기 위해 useEffect 안에서 Clean-up 함수를 호출한다.

useEffect(() => {
    return () => console.log(state);
}, [])

 

Clean-up 함수는 리렌더링 직후 의존성 배열의 state 중 변경된 값이 있다면 클로저에 의해 이전 시점의 state를 기준으로 실행되는 함수이다.

 

의존성 배열에 state가 들어 있으면 두 가지 경우에 실행된다.

  • 컴포넌트가 언마운트될 때
  • 해당 state의 값이 변경될 때

 

Clean-up 함수에서 해당 state를 찍어 보면 state가 변경되기 직전의 값이 출력될 것이다. 아래 코드가 그 예시이다.

export const Test = () => {
    const [name, setName] = useState<string>("doringri");

    useEffect(() => {
        return () => console.log(name);    // 버튼이 클릭됐어도 'doringri'가 출력됨
    }, [name]);

    const changeName = () => {
        setName("fish");
    }

    return (
        <button onClick={changeName}>
            이름 변경
        </button>
    )
}

 

만약 useEffect의 의존성 배열을 비워 놓는다면 컴포넌트가 언마운트될 때만 실행되기 때문에 setTimeout, setInterval을 초기화시키는 등 메모리 누수를 방지하는 여러 처리를 할 수가 있다.

 

위 코드에서 useEffect의 의존성 배열을 비워 놓는다면 그런 처리가 가능하다.

 

그런데, 여기서 컴포넌트가 언마운트될 때 이전 시점의 state가 아닌 현재 state 값을 가져오고 싶을 때가 있다.

이때 useRef를 사용한다.

 

useRef는 렌더링에 영향을 주지 않는 값을 참조할 때 쓰는 훅이다.

 

export const Test = () => {
    const [name, setName] = useState<string>("doringri");
    const nameRef = useRef<string>(name);

    useEffect(() => {
        nameRef.current = name;
    }, [name]);

    useEffect(() => {
        return () => console.log(nameRef.current);    // 버튼을 클릭했다면 언마운트 시 'fish' 출력
    }, []);

    const changeName = () => {
        setName("fish");
    }

    return (
        <button onClick={changeName}>
            이름 변경
        </button>
    )
}

 

name이라는 state를 의존성 배열로 가지고 있는 useEffect를 이용하여 값이 변경될 때마다 nameRef의 current 값을 업데이트시켰고, 이것을 언마운트될 때 가져와서 현재 값을 가져올 수 있게 되었다.

 

이처럼 DOM을 조작하는 작업 이외에도 useRef를 유용하게 사용할 수 있었다.