
import * as React from 'react';
import { useState, useRef, useEffect } from 'react';
import { createRoot } from 'react-dom/client';
function App() {
const [show, setShow] = useState(true)
return <div>
{show && <Child unmount={() => setShow(false)} />}
</div>;
}
function Child({ unmount }) {
const isMounted = useIsMounted()
useEffect(() => {
console.log(isMounted)
Promise.resolve(true).then(() => {
console.log(isMounted)
});
unmount();
}, []);
return null;
};
function useIsMounted() {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => isMounted.current = false;
}, []);
return isMounted.current;
}
const root = createRoot(document.getElementById('root'));
root.render(<App/>)
false
false
false 출력: useIsMounted()에서 반환한 isMounted의 값 false를 기억하고 출력합니다.상태값 변화 : Child의 useEffect 안에서 unmount()가 호출되어 재렌더됩니다.
useIsMounted의 cleanup 함수가 실행되어 Ref의 값은 false가 됩니다.
false 출력: isMounted는 첫번째 렌더에서 결정되었던 지역 변수(클로저) false입니다.
🤔 그럼 어떻게 해야 Ref값을 기억할까?
return isMounted.current(현재 방식)
이 방식은useIsMounted가 실행되는 그 찰나의 값을 찍어서 넘겨주는 방식입니다.이후
useEffect에서ref.current를 어떻게 하든 Child가 이미 받아버린false라는 값 자체는 절대로 변하지 않습니다. 그래서 두 번 다false가 나옵니다.
return isMounted(Ref 객체 반환 방식)
이 방식은 값이 들어있는 주소를 통째로 넘겨주는 방식입니다.
Promise.then이 실행될 때isMounted.current를 확인하면 그 순간 안에 들어있는 최신 상태값를 보게 됩니다.