본문 바로가기

프론트엔드/Next.js

routeChange event로 page transition loading UI 구현하기

  • 프로젝트: Co-Building
  • 키워드: routeChange, Router.events, page transition
  • 상황
    1. Next.js에서 Page가 전환되는 동안 페이지 중앙에 Loading UI를 그려주고자 한다.
    2. 모든 페이지에 해당하는 기능이니 Custom _app.js 파일에서 처리할 수 있는 방법을 찾는다.
  • 해결 방법
    1. 먼저 Loading UI 컴포넌트를 만든다. 이 프로젝트에서는 loading 상태임을 확인하는 boolean 변수를 SWR로 관리하고 있다.
        // Loading.jsx
      import React from 'react';
      import styled from '@emotion/styled';
      import useSWR from 'swr';
      import { LOADING_KEY } from '../swr/loading';
      import Image from 'next/image';
      
      const Loading = () => {
        const { data: loading } = useSWR(LOADING_KEY);
      
        if (!loading) return null;
        return (
          <FullContainer>
            <Image src="/loading.png" alt="" width={100} height={100} />
          </FullContainer>
        );
      };
      
      export default Loading;
      
      const FullContainer = styled.div`
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        
        ...
      `;


    2. 이제 _app.js에서 route가 변하는 순간을 detect 해야 한다. next/router 공식 문서를 읽어보면 해당 기능에 대한 설명을 발견할 수 있다. (https://nextjs.org/docs/api-reference/next/router#routerevents)

      Router.events listener의 'routeChange...' event를 사용하여 해결하면 된다. 페이지 전체에 걸친 로직이니 _app.js에서 useEffect를 사용하여 한 번만 호출한다.
        // _app.js
      function MyApp({ Component, pageProps }) {
        ...
        // page transition
        useEffect(() => {
          const start = () => {
            mutate(LOADING_KEY, true);
          };
          const end = () => {
            mutate(LOADING_KEY, false);
          };
      
          Router.events.on('routeChangeStart', start);
          Router.events.on('routeChangeComplete', end);
          Router.events.on('routeChangeError', end);
      
          return () => {
            Router.events.off('routeChangeStart', start);
            Router.events.off('routeChangeComplete', end);
            Router.events.off('routeChangeError', end);
          };
        }, []);
      
        return (
          <>
            ...
            <Component {...pageProps} />
            <Loading />
            ...
          </>
        );
      }
      
      export default MyApp;
      'routeChangeStart', 'routeChangeComplete', 'routeChangeError' event를 구독한 후 페이지 전환이 시작할 때 Loading UI를 켜고, 페이지 전환이 끝나거나 예외가 발생했을 때 UI를 끈다.

      이제 페이지를 이동할 때마다 화면 중앙에 Loading UI가 나타난다!