우리가 그동안 javascript 에서 Dom을 선택하기 위해선 getElementById 혹은 querySelector과 같은 함수를 사용해왔습니다
하지만 리액트에서 우리는 DOM을 직접 선택해야 하는 상황이 올때 무엇을 사용할까요?!
바로 ref 라는 것을 사용합니다.
특히 함수형 컴포넌트에서는 ref를 사용하기 위해 useRef 라는 Hook함수를 사용 합니다!
예시를 통해 useRef의 기능을 알아봅시다!
리액트 DOC에 정의된 useRef의 의미
useRef는 .current 프로퍼티로 전달된 인자(initialValue)로 초기화된 변경 가능한 ref 객체를 반환합니다.
const nameInput = useRef();
const onClick = () => {
nameInput.current.focus();
}
return(
<input ref={nameInput} />
<button onClick={onClick}>클릭</button>
)
const observer = useRef();
const ElementRef = useCallback(
// console.log(node) ref={ElementRef} 의 요소들을 전부 가져온다.
// <div>TEST</div>
node => {
// Ref 객체의 .current 값은 우리가 원하는 DOM 을 가르키게 됩니다.
if(node) observer.current.observe(node);
[],
);
return <div ref={ElementRef}>TEST</div>
본질적으로 useRef는 .current 프로퍼티에 변경 가능한 값을 담고 있는 “상자”와 같습니다.
만약
(useRef는 매번 렌더링을 할 때 동일한 ref 객체를 제공함!)
하나의 옵저버 객체는 단일한 threshold와 root를 가지지만 복수의 타겟 엘리먼트의 가시성 변화를 관찰할 수 있습니다.
(MDN Docs의 정의는 언제나 내게 너무 어려운 것.. ㅠㅠ)
쉬운말로 표현하자면 뷰포트와 설정한 요소의 교차점을 관찰하여 요소가 뷰포트에 노출된 여부를 알 수 있게 해줍니다.
new IntersectionObserver(callback[, options]);
const observer = useRef();
const ElementRef = useCallback(
// console.log(observer.current) 현재 관찰되고 있는 요소
node => {
if (observer.current) observer.current.disconnect();
// 최근 observer를 갖기위해 이전 observer disconnect 해주기
observer.current = new IntersectionObserver(entries => {
// entries는 아래 설명참조
if (entries[0].isIntersecting && hasMore) {
setPageNumber(prevPageNumber => prevPageNumber + 1);
}
});
if(node) observer.current.observe(node);
// 노드가 있으면 observer.current를 observe 해준다.
[],
);
return (
{data.map((item)=> <div>{item}<div>)}
);
entries는 IntersectionObserverEntry 인스턴스의 배열로 다음과 같은 프라퍼티(속성)을 갖습니다.
https://developer.mozilla.org/ko/docs/Web/API/IntersectionObserver