react 에서 const divRef = useRef(null) 이렇게 useRef 를 선언했다고 하자. 이 값은 당연히 div 태그의 ref 속성에 적용될 예정이다. 가장 간단한 방법으로 <div ref={divRef} /> 이렇게 적용할 수 있지만, 이렇게 말고 ref 속성에 콜백함수를 전달하며 넘길 수도 있다.
ref={(node) => { /* node는 DOM 또는 클래스 인스턴스 */ }}
react가 요소를 마운트 / 업데이트 / 언마운트할 때 이 함수를 호출해서 현재 참조 대상을 전달해주게된다.
null이 먼저 전달됨null -> 새 노드에 대해 실제 노드 순서로 호출null힘든 동적 목록 관리(여러 개의 노드 수집), 조건부로 ref 전환, 외부 라이브러리 초기화 / 해제 같은 정교한 타이밍 제어가 필요할 때 사용한다. 또한 연결 / 해제 이벤트 자체가 신호가 되므로, 초기화 / 정리 로직을 한곳에서 다룰 수 있는 장점이 있는 것이다.. 사실 여러개의 요소를 배열로 렌더링이 될때, 이때 하나씩의 ref를 참조하는 것이 필요할 때 사용하는게 제일 많긴하다.
아래 여러개의 비디오에서, <video> 태그에 ref로 함수형으로 적용하는 예시를 보자.
const videoRef = useRef<(HTMLVideoElement | null)[]>([]);
...
{
vidoeItems.map((item) => (
<video
ref={el => (videoRef.current[i] = el)}
/>
))
}
react는 해당 <video> 엘리먼트를 마운트하거나 언마운트할 때 이 함수를 실행시킨다. 인자로 들어오는 el은 마운트 시엔 실제 DOM 노드 (HTMLVideoElement) 이고, 언마운트 시엔 null이다.
즉,
1. 렌더 도중 react가 video를 DOM에 붙이고,
2. 그 즉시 이 콜백히 호출되고, videoRef.current[i]에 해당 DOM이 들어간다.
3. 나중에 언마운트되면 react가 한번 더 호출하면서 null로 정리해준다!
이 방식 덕분에, 여러개의 비디오를 렌더링하면서 특정 비디오는 재생시키고, 특정 비디오는 중지시키는 등의 작업을 제어할 수 있게 된다.