Next.js router.events를 활용하여 Page Loader 생성 [플랜 빙고 개발 노트 - ver. 0.1.10]

Yoon Robin·2023년 7월 30일
0

페이지를 이동할 때 마다 Page Loader를 생성하고 싶었다.
그런데 매 페이지의 파일마다 일일이 Page Loader를 추가하는 건 비효율적이라고 생각했다.

아예 pages/_app.js에서 처리할 수 있는 방법이 있을 거라 생각해서 공식문서를 읽었고, 역시 공식문서에 방법이 있었다.

router.events를 활용하여 Page Loader 보여주기

Next.js Router에는 지원되는 여러 이벤트들이 있다.
그중에 내가 사용한 이벤트는 다음과 같다.

  • routeChangeStart(url, { shallow })
    : 라우트가 바뀌기 시작할 때 작동한다.

  • routeChangeComplete(url, { shallow })
    : 라우트가 다 바뀌었을 때 작동한다.

  • routeChangeError(err, url, { shallow })
    : 라우트가 바뀌는 중 에러가 발생하거나 라우트를 불러오는 걸 취소할 때 작동한다.

ℹ️ 참고로 이 셋 모두 파라미터가 없어도 동작한다.

공식 문서에서 나온 예시 코드는 다음과 같다.

import { useEffect } from 'react'
import { useRouter } from 'next/router'
 
export default function MyApp({ Component, pageProps }) {
  const router = useRouter()
 
  useEffect(() => {
    const handleRouteChange = (url, { shallow }) => {
      console.log(
        `App is changing to ${url} ${
          shallow ? 'with' : 'without'
        } shallow routing`
      )
    }
 
    router.events.on('routeChangeStart', handleRouteChange)
 
    // If the component is unmounted, unsubscribe
    // from the event with the `off` method:
    return () => {
      router.events.off('routeChangeStart', handleRouteChange)
    }
  }, [router])
 
  return <Component {...pageProps} />
}

useEffect를 사용하여 router를 동작할 때마다 이벤트를 사용할 수 있는 걸 알 수 있다.

이를 기반으로 나는 다음과 같이 코드를 짰다.

pages/_app.js 전체 코드

import "@/styles/globals.css";
import Head from "next/head";
import { useState, useEffect } from "react";
import { useRouter } from "next/router";
import LoadingSpinner from "@/components/parts/LoadingSpinner";

function App({ Component, pageProps }) {
 const [isLoading, setIsLoading] = useState(false);
  const router = useRouter();

  useEffect(() => {
    const handleRouteChange = () => setIsLoading(true);
    const handleRouteComplete = () => setIsLoading(false);
    const handleRouteChangeError = (err, url) => {
      if (err.cancelled) {
        console.log(`Route to ${url} was cancelled!`);
      }
      setIsLoading(false);
    };

    router.events.on("routeChangeStart", handleRouteChange);
    router.events.on("routeChangeComplete", handleRouteComplete);
    router.events.on("routeChangeError", handleRouteChangeError);

    return () => {
      router.events.off("routeChangeStart", handleRouteChange);
      router.events.off("routeChangeComplete", handleRouteComplete);
      router.events.off("routeChangeError", handleRouteChangeError);
    };
  }, [router]);
  return (
    <>
      <Head>
        {/* 생략 */}
      </Head>

      {isLoading ? (
        <div>
          <LoadingSpinner />
        </div>
      ) : (
        <Component {...pageProps} />
      )}
    </>
  );
}

export default App;

그 외 참고 자료
next/router event 감지 및 이를 활용한 page loader

profile
신입 프론트엔드 개발자

2개의 댓글

comment-user-thumbnail
2023년 7월 31일

감사합니다. 이런 정보를 나눠주셔서 좋아요.

1개의 답글