최근에 캐시된 이미지를 사용하기 위해 useRef에 캐시되어야 할 id를 저장하고 캐시여부를 판단해야 하는 상황이 있었습니다..!
관련해서 오늘은 useRef와 관련된 사실을 알아보겠습니다!
먼저 내가 원했던 동작은 useRef를 선언한 컴포넌트가 unmount 되어도 그 값이 유지되어서 다음에 컴포넌트가 mount되어도 동일한 useRef 값을 사용하고 싶었습니다!
다음 코드를 살펴보자
//App.js
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button
onClick={() => {
setIsOpen(!isOpen);
}}
>
click
</button>
{isOpen && <UseRefTest />}
</div>
);
}
먼저 App.js에 state를 바꾸는 버튼을 하나 만들어주고, 버튼이 클릭될때마다 UseRefTest라는 컴포넌트가 렌더링 되도록 했습니다.
// UseRefTest.jsx
const UseRefTest = () => {
const testRef = useRef([]);
useEffect(() => {
console.log("init", testRef.current);
}, []);
return (
<div>
<button
onClick={() => {
testRef.current.push("aa");
}}
>
refClick
</button>
<button
onClick={() => {
console.log(testRef.current);
}}
>
refConfirm
</button>
</div>
);
};
다음으로 UseRefTest라는 이름의 컴포넌트를 만들어줬는데, 처음 렌더링 될때 useRef의 값을 콘솔로 찍고 useRef 객체에 값을 추가하는 버튼과 현재 useRef에 담겨진 값을 콘솔에 찍는 버튼을 만들어줬다.
결과는..?
맨 처음 UseRefTest컴포넌트가 렌더링 될 때는 빈배열,
refClick을 통해 useRef의 값을 바꿔주고 refConfirm으로 확인해주면 정상적으로 값이 출력됩니다.
그리고 click을 눌러 UseRefTest컴포넌트를 unmount시켜주고 다시 mount시켜주면?
기존에 있던 useRef의 값이 초기화 됩니다.
리액트 공식문서를 살펴보니 매우 초보적인 실수를 했다는걸 알 수 있었습니다..ㅎㅎ
(그래도 기록을 통해 명확히 아는게 더 좋겠죠? 그렇다고 해주세요..ㅜㅜ)
useRef는 .current 프로퍼티로 전달된 인자(initialValue)로 초기화된 변경 가능한 ref 객체를 반환합니다. 반환된 객체는 컴포넌트의 전 생애주기를 통해 유지될 것입니다. - react 공식문서 중-
그렇다. useRef는 unmount시에서도 유지되는게 아니라 컴포넌트의 전생애주기에서만 유지가 되는 것이다!
useRef에 대한 자료를 찾아보면서 새로운 사실을 알게 되었는데, 잠시 UseRefTest 컴포넌트를 살펴보자
//UseRefTest.jsx
const UseRefTest = () => {
const testRef = useRef([]);
...
useEffect(() => {
console.log("progress", testRef.current);
}, [testRef.current.length]);
...
}
useRef가 바뀔때마다 해당 값을 확인해보고 싶어서 useEffect 의존성에 ref객체를 넣어주었습니다.
이렇게 하면 맨 처음 렌더링 될 때 말고는 (useEffect는 의존성에 무엇이 들어가있든 무조건 처음 한번은 실행되므로) 실행되지 않습니다.
useRef의 업데이트 된 값은 다음 렌더링이 진행되기 전까지는 바뀐 값이 무엇인지 알 수 없기 때문입니다.
Keep in mind that useRef doesn’t notify you when its content changes. - 리액트 공식문서 중 useRef 설명 일부 -
정확하게 위 상황을 말해주는지는 확실하지 않지만 테스트를 진행해봤을 때 useRef의 변경이 감지 되지 않는 것이 확인 되었으므로 맞는 것 같습니다.
최종적으로 unmount되어도 useRef의 값을 유지하기 위해서 부모컴포넌트에 useRef를 선언하고 props로 넘겨주어 자식 컴포넌트에서 수정이 이루어지게 했습니다!!(너무 간단한 해결법이었습니다..ㅎㅎ)
이렇게 useRef에 대한 내용을 살펴보았습니다. 다만 적고 보니 너무 기초적인 내용을 놓치고 있었다는 생각이 드네요..
다른 분야에서도 그렇듯 리액트에서도 기본기가 중요함을 다시한번 느끼면서 글을 마치겠습니다.
끝!
'웹 프로그래밍 > FrontEnd' 카테고리의 다른 글
[React] useState? useRef? (feat.단축키 추가) (0) | 2023.01.29 |
---|---|
[JavaScript] Bind가 뭐죠? (0) | 2021.09.15 |
[Javascript] fetch()로 API 요청 보내기 (0) | 2021.09.14 |
이벤트 버블링, 캡쳐, 위임 (0) | 2021.09.10 |