scrollRestoration! 스크롤아 돌아와줘!

Hwang Tae Young·2023년 2월 1일
0

🚀 구현하고자 하는 것

포켓몬을 이것저것 끝내고 추가기능으로 갑자기 생각난!
원래 스크롤 위치 기억하게 만들기 대부분에 사이트에 적용이 되어있고, 마우스나 키보드로 뒤로가기를 눌렀을 시 원래 보던 스크롤로 가는 것을 구현해보자 했다.

🚀 사용한 방식

적용한 방식은

  const [saveScrollY, setSaveScrollY] = useState<number>(0);
  const [restoreScrollY, setRestoreScrollY] = useState<number>(0);

  useEffect(() => {
    const onRouteChangeStart = () => {
      setRestoreScrollY(saveScrollY);
      setSaveScrollY(window.scrollY);
    };
    const onRouteChangeComplete = () => {
      window.scroll(0, restoreScrollY);
    };

    router.events.on("routeChangeStart", onRouteChangeStart);
    router.events.on("routeChangeComplete", onRouteChangeComplete);

    return () => {
      router.events.off("routeChangeStart", onRouteChangeStart);
      router.events.off("routeChangeComplete", onRouteChangeComplete);
    };
  }, [saveScrollY, router, restoreScrollY]);

next.js의 router.event를 사용하여 완성하였다.
routeChangeStart는 라우터를 시작하기 전에 동작하기 때문에 현재 페이지를 나타낸다고 볼 수 있고,
routeChangeComplete는 라우터가 완료된 시점의 페이지를 나타낸다고 볼 수 있다. 이것을 이용해
현재 페이지의 scroll값은 saveScroll에 저장해주고 복원해줘야하는 스크롤값은 restoreScrollY에 저장하여 구현하였다.

이렇게 라우터를 시작하기전에 스크롤값을 state에 저장시켜해보았다. 처음에는 하나의 state만 있어도 될 줄 알고 했다가 3~4시간을 삽질을 하고,,,,, state의 값을 2개로 바꾸어 진행을 하니 동작을 잘 했다. 여기서 문제 되는 로고를 눌렀을 때도 똑같이 동작하는게 문제였다. 내가 원한것은 뒤로가기 동작에서만 동작하는 것을 원했었다. 그래서 아래와 같이 코드를 변경하였다.

  const [saveScrollY, setSaveScrollY] = useState(0);
  const [restoreScrollY, setRestoreScrollY] = useState(0);
  const [historyLength, setHistoryLength] = useState(0);

  useEffect(() => {
    if (window.history.length !== historyLength) {
      setHistoryLength(window.history.length);
      return;
    }
    const onRouteChangeStart = () => {
      setRestoreScrollY(saveScrollY);
      setSaveScrollY(window.scrollY);
    };
    const onRouteChangeComplete = () => {
      window.scroll(0, restoreScrollY);
    };

    router.events.on("routeChangeStart", onRouteChangeStart);
    router.events.on("routeChangeComplete", onRouteChangeComplete);

    return () => {
      router.events.off("routeChangeStart", onRouteChangeStart);
      router.events.off("routeChangeComplete", onRouteChangeComplete);
    };
  }, [saveScrollY, router, restoreScrollY, historyLength]);

window.history.length의 숫자는 뒤로가기가 아닌 새로운 페이지로 갔을때, 늘어나는 것을 이용하여 window.history.length의 length가 바뀌지 않으면 뒤로가기나 앞으로가기를 한 것으로 생각되어 동작되었다.

참고 : 깔끔하지만 화려하고 단조롭지만 컬러풀한 블로그 개발기 - 2

✅ 후기

참고했던 블로그에서는 세션스토리지를 이용해서 동작을 시키는데 포켓몬 번호가 898번째까지 있는 이 프로젝트에서는 세션스토리지의 용량이 버텨주지 못할 것 같아서 state로 바꾸었고, 처음에 하나의 state로 동작시킬 수 있을 것이라 생각했던게 너무 잘못된 생각이었던 것 같다. 하면서 느낀 점은 차분하게 내가 구현하고자 하는 것을 아는것과 내가 사용할 것들이 어떻게 동작시키는지 정리해서 진행하면 더 좋았을 것 같다. 이미 알고 있던 것들인데도 항상 까먹는 것 같으니 더 잘 상기시켜봐야겠다!

profile
더 나은 개발자가 되기 위해...☆

0개의 댓글