본문 바로가기
프론트엔드

Next.js + TypeScript + @reduxjs/toolkit 사용하기 < 1 / 2 > 개인기록

by goodchuck 2024. 5. 22.

목차

     상태라이브러리인 redux를 Next.js + TypeScript에서 써보자

     

     진행과정

    store.ts  생성

    src/libs 위치에 store.ts파일을 생성해준다. 그리고 아래 코드처럼 작성을해준다.

    import { Action, configureStore, ThunkAction } from "@reduxjs/toolkit";
    import { counterReducer } from "./features/counter";
    import { authReducer } from "./features/auth/slices/auth.slice";
    
    export const makeStore = () => {
        return configureStore({
            reducer: {
                counter: counterReducer,
                auth: authReducer,
            },
        });
    };
    
    export type AppStore = ReturnType<typeof makeStore>;
    
    export type RootState = ReturnType<AppStore["getState"]>;
    export type AppDispatch = AppStore["dispatch"];
    export type AppThunk<ReturnType = void> = ThunkAction<
        ReturnType,
        RootState,
        unknown,
        Action<string>
    >;

    TypeScript를 사용하기때문에 위 코드처럼 선언을 하여 사용한다. 역할은 rootReducer이다.

    counter이랑 auth은 이미 만들어져있는것이기때문에 참고정도로만 생각하면된다.

     

    hooks.ts 생성

    src/libs 에 hooks.ts 파일을 생성한다.

    import { useDispatch, useSelector, useStore } from "react-redux";
    import type { AppDispatch, AppStore, RootState } from "./store";
    
    // Use throughout your app instead of plain `useDispatch` and `useSelector`
    export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
    export const useAppSelector = useSelector.withTypes<RootState>();
    export const useAppStore = useStore.withTypes<AppStore>();

     

    StoreProvider.tsx 생성

    아래 코드는 /src/app/StoreProvider.tsx파일이다. Next.js에선 해당 Provider로 감싸주는게 필요하다.

    'use client';
    import { useRef } from "react";
    import { Provider } from "react-redux";
    import { makeStore, AppStore } from "@/libs/store";
    
    export default function StoreProvider({
        children
    }: {
        children: React.ReactNode
    }) {
        const storeRef = useRef<AppStore>()
        if (!storeRef.current) {
            // Create the store instance the first time this renders
            storeRef.current = makeStore()
        }
        return <Provider store={storeRef.current}>{children}</Provider>
    }

     

    src/app/layout.tsx에 감싸기

    import type { Metadata } from "next";
    import { Inter } from "next/font/google";
    import "./globals.css";
    import StoreProvider from "./StoreProvider";
    
    const inter = Inter({ subsets: ["latin"] });
    
    export const metadata: Metadata = {
      title: "Create Next App",
      description: "Generated by create next app",
    };
    
    
    export default function RootLayout({
      children,
    }: Readonly<{
      children: React.ReactNode;
    }>) {
      return (
        <StoreProvider>  <---------- 여기에 추가
          <html lang="en">
            <body className={inter.className}>
                {children}
            </body>
          </html>
        </StoreProvider> <---------- 여기에 추가
    
    
      );
    }

    위 코드처럼 감싸준다 어디에 감싸는건 자유로보이지만 일단 전체적으로 redux를 사용할 것이기때문에 

    루트 레이아웃에다가 감싸주었다.

     

    redux 사용할 준비완료

    위 작업들을 마쳤다면 이제 해당 layout안의 페이지들은 redux를 사용할 수 있다.