프로젝트중 매인피드의 스크롤 관련 훅에서 문제가 발생했다.
해당 코드는 useScroll이라는 커스텀 훅이다
export const useScroll = () => {
const [offset, setOffset] = useRafState({ x: 0, y: 0 });
const ref = useRef(null);
useEffect(() => {
const element = ref.current;
if (!element) return null;
const handleScroll = () => {
setOffset({
x: ref.current.scrollLeft,
y: ref.current.scrollTop,
});
};
element.addEventListener('scroll', handleScroll, { passive: true });
return () => element.removeEventListener('scroll', handleScroll);
}, [ref, setOffset]);
return [ref, offset];
};
해당 코드는 mainFeed Page에서 발췌했다.
const [firstLoading, setFirstLoading] = useState(true);
const [ref, isScrollDown] = useScrollDown();
{firstLoading ? (
<Spinner />
) : (
<S.MainFeedPageContainer
ref={ref}
className={!isScrollDown ? 'bannerShown' : null}
>
mainFeed 페이지에서 useScroll훅을 내부에서 사용하는 useScrollDown 훅을 사용한다.
현재 mainFeed 페이지에서는 firstLoading 상태값에 따라서, MainFeedPageContainer 컴포넌트가 렌더링이 되는데
firstLoading === true 일때에는 해당 컴포넌트는 렌더링이 되지 않는다.
문제가 뭔지 보니
Warning: useEffect must not return anything besides a function, which is used for clean-up. You returned null. If your effect does not require clean up, return undefined (or nothing).
에러이다 .
해서 if (!element) return null
해당 코드에서 return null 이 아닌 retrun 으로 수정을 하니 해결이 되었다.
useEffect return에는 null을 사용해서는 안된다고 한다.
왜 일까?
mainFeedPage가 리렌더링이 되고 난후에는
useScroll useEffect 내부에서는 Ref로 할당한 dom을 가져오지 못하는 문제가 있었다.
해당문제는 mainFeedPage에서는 useScrollDown으로 받아온 Ref를 할당한 dom이 확인 가능하지만
useScroll 내부에서는 확인이 안되었다. 즉 useEffect가 재실행이 안되고 있었다.
useEffect deps에는 [ref, setOffset]
를 할당을 했는데 왜 안되는건지 고민한결과.
ref은 객체로 들오온다
ref안에는 current가 있다 즉 current가 변경이 되었을때 useEffect가 실행되게 바꾸면 어떻게 될까?
[ref.current, setOffset]
로 변경하니 실행이 됐다.
useEffect 의 dependency array에 object를 넣으면 object의 reference가 변경될 때 마다 실행된다.
해서 ref의 객체 참조가 변경이 안되고 current값만 변경이 되었기 때문에 이런 현상이 발생했다.