❗문제상황
프로젝트에서 페이지 이동 시 로딩 스피너로 로딩처리를 해주었다.
하지만 로딩이 오래걸리지 않는 경우에는 로딩스피너가 잠깐 보였다가 없어지면서 깜빡이는 것 같은 느낌을 주고 실제로 로딩 시간이 길지 않았음에도 사용자에게 로딩이 있었다라는 인식을 주는 것이 좋지 않다고 생각했다. 따라서 특정 시간 이상 로딩이 걸리는 경우에만 보여주기로 결정하였다.
⌛라우터 로딩 적용하기
먼저 페이지 이동 로딩은 라우터 이벤트를 사용하여 적용해줄 수 있다.
import Router from 'next/router';
import { useEffect, useState } from 'react';
export const useRouterLoading = () => {
const [nowLoading, setNowLoading] = useState(false);
useEffect(() => {
const start = () => {
setNowLoading(true);
};
const end = () => {
setNowLoading(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 { nowLoading };
};
- routerChangeStart: 주소가 변경되기 시작할 때 호출
- routerChangeComplete: 주소 변경이 완료되었을 때 호출
- routerChangeError: 주소 변경 중 에러가 발생했을 때, 취소 되었을 때 호출
이렇게 커스텀 훅을 만들어주고 _app.tsx에서 nowLoading의 값에 따라 로딩 스피너를 보여주도록 처리하면 된다.
//_app.tsx
<QueryClientProvider client={queryClient}>
...
<main
className={`${notoSans.className} ${lato.variable} ${prettyNight.variable} h-full`}
>
{nowLoading && <LoadingSpinner />}
{getLayout(<Component {...pageProps} />)}
<LoginModal />
</main>
...
</QueryClientProvider>
여기서 로딩 시간이 0.5초가 지났을 때만 로딩스피너를 보여주고 싶기 때문에 커스텀 훅에서 setTimeout을 이용해여 시간을 설정해주면 된다.
⏱️setTimeout으로 시간 지정하기
import Router from 'next/router';
import { useEffect, useState } from 'react';
export const useLoading = () => {
const [nowLoading, setNowLoading] = useState(false);
useEffect(() => {
let timer: ReturnType<typeof setTimeout>;
const start = () => {
timer = setTimeout(() => {
setNowLoading(true);
}, 500);
};
const end = () => {
clearTimeout(timer);
setNowLoading(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 { nowLoading };
};
setTimeout을 쓸 땐 타입 지정을 하지 않아도 되는데 clearTimeout을 할 땐 타입을 지정해주어야 한다. node에서 사용하는지, window에서 사용하는지에 따라 타입을 다르게 설정할 수 있는데 ReturnType을 사용하면 신경쓰지 않고 두 곳 모두에서 사용할 수 있다고 한다!
✅적용 결과
- 적용 이전
- 적용 이후
setTimeout으로 시간을 지정했기 때문에 바로 로딩이 완료된 경우에는 로딩 스피너가 뜨지 않는 것을 볼 수 있었다!🎉🎉
'개발 공부 > React' 카테고리의 다른 글
react slick 특정 슬라이드에서 dots 없애기 (0) | 2023.07.31 |
---|---|
[nextJS] 성능 최적화 하기(lighthouse, 빌드 용량 개선) (0) | 2023.07.25 |
[next + tanstack query] 낙관적 업데이트 적용하기 (0) | 2023.07.22 |
무한스크롤 스크롤 위치 기억하기 (0) | 2023.07.10 |
color-thief 라이브러리 type 지정하기 (0) | 2023.07.02 |