useMediaQuery
훅을 사용하여 모바일 화면에서는 로딩 아이콘을 오른쪽 상단, 데스크톱 화면에서는 오른쪽 하단에 보여주도록 구현한다.Spinner
컴포넌트를 사용하여 구현하였다.//Loading.tsx
export default function Loading() {
const [mobileView] = useMediaQuery("(max-width: 768px)", {
ssr: true,
fallback: false, // return false on the server, and re-evaluate on the client side
});
return (
<>
<Center w="100vw" h="100vh" zIndex={"99"} position={"fixed"}>
{mobileView ? (
<Center
pos={"absolute"}
top={10}
right={10}
bgColor={bgColor}
padding={3}
rounded={10}
>
<Spinner top={10} right={10} size={"md"} color={color} />
</Center>
) : (
<Center
pos={"absolute"}
bottom={10}
right={10}
bgColor={bgColor}
padding={3}
rounded={10}
>
<Spinner top={10} right={10} size={"md"} color={color} />
</Center>
)}
</Center>
</>
);
}
Next.js 애플리케이션에서 로딩 컴포넌트를 구현하는 방법이다.
useEffect
훅을 사용하여 라우터 이벤트를 등록하고, 페이지 이동이 시작될 때 로딩 상태를 true
로 변경한다. 이때, 로딩 컴포넌트를 렌더링하기 위해useState
훅을 사용한다.
const [loading, setLoading] = useState(false);
useEffect(() => {
const showRoute = [
"/",
"/notes/:category",
"/entry/:titleUrl/:id",
"/guestbook",
];
const start = (url: any) => {
if (showRoute.find((route) => String(url).includes(route))) {
setLoading(true);
}
};
const end = (url: any) => {
if (showRoute.find((route) => String(url).includes(route))) {
setLoading(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);
};
}, []);
위 코드에서 showRoute
는 로딩 컴포넌트를 표시할 페이지 경로를 배열로 정의한다. Router.events.on()
메서드를 사용하여 라우터 이벤트에 대한 핸들러를 등록하고, 페이지 이동이 시작될 때 start()
함수가 실행된다. start()
함수는 showRoute
에 포함된 경로 중 현재 페이지 경로가 포함되어 있으면 로딩 상태를 true
로 변경한다. 페이지 이동이 완료되면 end()
함수가 실행되어 로딩 상태를 false
로 변경한다.
마지막으로, 로딩 컴포넌트를 조건부 렌더링하여 로딩 상태가 true
일 때만 보여주도록 한다.
//_app.tsx
return (
<ChakraProvider theme={theme}>
{loading && <Loading />}
<RecoilRoot>
<AnimatePresence
initial={true}
onExitComplete={() => window.scrollTo(0, 0)}
>
{mobileView ? <HeaderMobile /> : <Header />}
<Component {...pageProps} />
<Footer />
</AnimatePresence>
</RecoilRoot>
</ChakraProvider>
);
위 코드에서 loading && <Loading />
은 loading 상태가 true
일 때만 로딩 컴포넌트를 렌더링한다.