스크롤에 맞춰 애니메이션 CSS를 주기위해서 IntersectionObserver API를 활용하게 되었다.
다른 컴포넌트에서도 사용해야 했기에 훅스로 만들려고 했었다.
초기에는 ref값을 target으로 훅스 매개 변수로 전달해 주었다.
export default function useIntersectionObserver(
option: IntersectionObserverInit,
Fn: any,
target: any
) {
if (!targets) {
return;
}
const callback: IntersectionObserverCallback = (entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log("intersection");
}
Fn(entry.isIntersecting);
});
};
const obeserver = new IntersectionObserver(callback, option);
return obeserver.observe(target);
}
type 을 any로 쓴 이유는 초창기에 전달해주는 함수들을 모아서 타입을 정리해서 만들기 위해서 처음에는 any로 타입을 지정해주었다.
이렇게 훅스를 만들고 컴포넌트에서는 useState와 useRef를 활용해서 훅스를 사용했다.
대략 이런식
const ref = useRef<HTMLDivElement>(null);
const [isTextCross, setIsTextCross] = useState(false);
const observerOption = {
threshold: 0.3,
};
const crossFn = (isCrossed: boolean) => {
if (isCrossed) {
setIsTextCross(true);
} else {
setIsTextCross(false);
}
};
이렇게 사용하려고 보니
초기 useRef가 null값이 여서 처음 렌더링시 if(!targets){return} 이곳에서 걸려서 실행되지 않았다.
함수를 체크하기 위해서 계속 코드를 저장해서 핫픽스로 리렌더링되어서 useRef가 생겨서 문제없이 기능을 체크하다가
새로고침을 해보니 애니메이션이 실행되지 않는 것이었다. 이유를 알고 보니 useRef가 null값이다..
어찌 해결해야 싶나 해서 useEffect에 훅스를 넣어도 useEffect에서 훅스를 사용하면 안된다는 에러도 만나고
고민고민하다가 훅스 자체로 ref를 리턴해서 ref를 지정해주자 라고 생각하고 코드를 수정하게 되었다.
수정한 훅스는 아래와 같다
import { useEffect, useRef, MutableRefObject } from "react";
function useIntersectionObserver(
callback: (isIntersecting: boolean) => void,
options?: IntersectionObserverInit
): MutableRefObject<HTMLDivElement | null> {
const targetRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
callback(entry.isIntersecting);
});
}, options);
if (targetRef.current) {
observer.observe(targetRef.current);
}
return () => {
if (targetRef.current) {
observer.unobserve(targetRef.current);
}
};
}, [callback, options]);
return targetRef;
}
export default useIntersectionObserver;
훅스 자체에서 ref를 생성해서 리턴해주고 컴포넌트에서는 훅스를 변수로 할당해주고 할당된 변수를 엘리먼트 ref로 전달해주었다.
const tokenTextRef = useIntersectionObserver(crossFn, observerOption);
<div
ref={tokenTextRef}
className="flex flex-col justify-center items-center min-h-[1150px] text-white bg-[url('./images/selo_flow_bg.webp')] bg-cover bg-center"
>
이렇게 설정해주었다.
처음에는 컴포넌트에서 useRef를 설정해주지 않아서 target을 잘 찾을수 있을까 걱정도 했지만 훅스에서 리턴 값으로 ref를 리턴해주니 에러도 나지않고 애니메이션도 잘 작동하게 되었다.
컴포넌트에서 ref를 설정해주지 않고 훅스에서 ref를 설정해주고 리턴한 값을 컴포넌트 엘리먼트 ref에 할당해도 정확하게 작동한다 라는 개념을 알게 되었다 !