useEffect & intersectionObserver API를 활용해보자.

YOUNGJOO-YOON·2022년 1월 5일
0

TS+REACT

목록 보기
10/10
post-custom-banner

사용하기 나름이겠지만 navBar를 기준으로 io를 구현해보자.

요청받은 사항은 아래의 두가지 였다.

  1. 화면의 최상단에 있는 경우 navBar의 배경색을 투명하게한다.

  2. 스크롤이 내려가면 화면을 따라 navBar가 따라오고 배경색이 흰색이 된다.


<nav>
...
</nav>

위와 같이 nav 태그 내부에 당신의 navBar가 있다고 하자.

lint에 오류가 있지만 상관하지 않고 기능을 구현하기로한다

우선 dom의 형태를 변경해준다.

<div>
  <div /> // 1
  <nav> // 2
  ...
  </nav>
  
</div>

위와 같은 형태를 한 이유는 nav 태그 위의 div가 필요해서이다.

1의 역할은 화면에 보이면 false를 반환한다라는 이벤트를 하는 io를 심어놓는다.

2의 역할은 화면에 안보이면 true를 반환한다라는 이벤트를 하는 io를 심어놓는다.

즉 스위치를 만든 것이다.

아래는 실제 코드의 일부이다.

const Navigation = () => {
  const [showMenu, setShowMenu] = useState(false);
  const toggleMenu = () => setShowMenu(!showMenu);
  const [isNavBgVisible, setIsNavBgVisible] = useState(false);
  const navIoRef = useRef<any>();
  const ceilingIoRef = useRef<any>();
  const topObCallBack = () => {
    setIsNavBgVisible(false);
  };
  const navObCallBack = () => {
    console.log(`callback!`);
    setIsNavBgVisible(true);
  };
  useEffect(() => {
    const observeWhenNavDisappear: IntersectionObserver = new IntersectionObserver(([entries]: any): void => {
      if (!entries.isIntersecting) {
        navObCallBack();
        observeWhenNavDisappear.unobserve(entries.target);
      }
    });
  // lint error
    navIoRef.current && observeWhenNavDisappear.observe(navIoRef.current);
  }, [navIoRef, isNavBgVisible]);
  useEffect(() => {
    const observeWhenCeilingAppear: IntersectionObserver = new IntersectionObserver(([entries]) => {
      if (entries.isIntersecting) {
        topObCallBack();
      }
    });
    // lint error
    ceilingIoRef.current && observeWhenCeilingAppear.observe(ceilingIoRef.current);
  }, [ceilingIoRef, isNavBgVisible]);

  return (
    <div>
      <div ref={ceilingIoRef} />
      <nav
        ref={navIoRef}
        className={tw(`bg-white ${isNavBgVisible ? `bg-opacity-100 fixed` : `bg-opacity-0  `}  absolute z-20 w-full`)}
      >
        ...
      </nav>
      ...
      </div>

react의 life cycle을 고려하여 useEffect와 useRef를 사용해야 한다.
문법적으로 걸리는 부분은 주석으로 lint error이라 써놓았고

ref를 선언하는데 any 타입을 사용한 것이다.

하지만 위 코드의 일부는 landingpage에서 사용되고 nextjs를 거쳐 compile되기 때문에 결국 static한 html 파일이 된다.

따라서 lint나 type 선언이 지저분해도 어느정도는 감안이 되는 부분이다.

잘 생각해보면 useEffect와 io 하나에 모든 기능을 넣을 수 있겠지만
굳이 그래야 하는가? 라는 생각도 들어 useEffect를 두개로 나누었다.

profile
이 블로그의 글은 제 생각을 정리한 글과 인터넷 어딘가에서 배운 것을 정리한 글입니다. 출처는 되도록 남기도록 하겠습니다. 수정 및 건의 오류 등이 있으면 언제든지 댓글 부탁드립니다.
post-custom-banner

0개의 댓글