목차
Next.js 14이상 app라우터에서 페이지 로딩효과 추가하기
Next.js 에서 app라우터로 개발을 하는 도중 라우터 이동전 로딩효과를 주는게 필요하였습니다.
사용 버전
- react : ^18
- zustand : ^4.5.2
- next : 14.1.0
진행과정
loadingStore.ts 추가
/src/store/loadingStore.ts파일을 만들어줍니다.
import { create } from 'zustand';
interface LoadingState {
isLoading: boolean;
}
interface LoadingActions {
setLoading: (loading: boolean) => void;
}
const useLoadingStore = create<LoadingState & LoadingActions>((set) => ({
isLoading: false,
setLoading: (loading: boolean) => set({ isLoading: loading }),
}));
export default useLoadingStore;
RouteChangeHandler.tsx 추가
'use client';
import React, { useEffect, useTransition } from 'react';
import { usePathname, useRouter } from 'next/navigation';
import useLoadingStore from '@/store/loadingStore';
const RouteChangeHandler: React.FC = () => {
const setLoading = useLoadingStore((state) => state.setLoading);
const router = useRouter();
const [isPending, startTransition] = useTransition();
const pathname = usePathname();
useEffect(() => {
setLoading(isPending);
}, [isPending, setLoading]);
useEffect(() => {
setLoading(false);
}, [pathname, setLoading]);
return null;
};
export default RouteChangeHandler;
LoadingSpinner.tsx, LoadingSpinner.styles.ts 추가
LoadingSpinner.tsx
/src/components/Loading/Spinner/LoadingSpinner.tsx
'use client';
import React from 'react';
import useLoadingStore from '@/store/loadingStore';
import { StyledSpinner, StyledSpinnerOverlay } from './LoadingSpinner.styles';
const LoadingSpinner: React.FC = () => {
const isLoading = useLoadingStore((state) => state.isLoading);
if (!isLoading) return null;
return (
<StyledSpinnerOverlay>
<StyledSpinner />
</StyledSpinnerOverlay>
);
};
export default LoadingSpinner;
LoadingSpinner.styles.ts
/src/components/Loading/Spinner/LoadingSpinner.styles.tsx
import styled from 'styled-components';
export const StyledSpinnerOverlay = styled.div`
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(255, 255, 255, 0.7);
z-index: 9999;
`;
export const StyledSpinner = styled.div`
border: 16px solid #f3f3f3;
border-top: 16px solid #3498db;
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`;
Layout.tsx에 추가
src/app/layout.tsx
import type { Metadata } from 'next';
import { Flex } from 'antd';
import './globals.css';
import LoadingSpinner from '@/components/Loading/Spinner/LoadingSpinner';
import RouteChangeHandler from '@/components/RouteChangeHandler';
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<head>
</head>
<body >
<Flex vertical style={{ width: '100%' }}>
<LoadingSpinner />
<RouteChangeHandler />
{children}
</Flex>
</body>
</html>
);
}
로딩을 줄 컴포넌트에서 로딩 주기
'use client';
import React from 'react';
import { Avatar, Button, Card, Image } from 'antd';
import { useRouter } from 'next/navigation';
import useLoadingStore from '@/store/loadingStore';
const { Meta } = Card;
type Props = {
assistant: any;
isPreparing?: boolean;
};
const AssistantCard = ({ assistant, isPreparing = false }: Props) => {
const router = useRouter();
const setLoading = useLoadingStore((state) => state.setLoading);
const onHandleClickBtn = (assistantId: string) => {
setLoading(true);
router.push(`assistant/chatting/${assistantId}`);
};
...생략
};
export default AssistantCard;
useLoadingStore를 가져오고 setLoading(true)로 해주면 끝!
router이동 전에 로딩바가 사이트 중앙에서 빙빙돌고있으면 정상 반영된거다.
적용사진
'Next.js' 카테고리의 다른 글
[Next.js, socket.io] Next.js에서 socket.io 공식 사용하기 (0) | 2024.06.07 |
---|---|
[Next.js, styled-components] Next.js에 styled-components 설정하기 (0) | 2024.06.07 |
[Next.js,TS] 특정폴더에만 Eslint 적용하기 (0) | 2024.05.30 |
[Next.js, TypeScript] airbnb 및 커스텀 TS 세팅 (1) | 2024.05.29 |
[Next.js]웹 페이지 전환 효과를 주는 방법들 (0) | 2024.05.24 |