Next.js + Redux-Toolkit

devPomme·2021년 10월 18일
1

Next.js + Redux

목록 보기
1/2
post-custom-banner

로그인한 관리자 정보 저장하고 전역 store에서 관리하기

필요한 라이브러리
reduxjs/toolkit: Redux를 사용할 때 store 생성, 액션 타입 지정, 리듀서 함수 등 작성해야하는 코드양을 줄이고 불필요한 보일러플레이팅을 지양하기 위해서 사용.

react-redux: useSelector, useCallback 로 각 컴포넌트에서 store 접근하기 위해서 사용
next-redux-wrapper: Next.js에서 각 페이지 컴포넌트의 getInitialProps, getServerSideProps, getStaticProps 로 store에 접근하기 위해서 사용
redux-logger: 브라우저 환경에서 store 변화를 직관적으로 보기 위해서 사용

$ yarn add @reduxjs/toolkit react-redux next-redux-wrapper
$ yarn add redux-logger -D 

/* src/store/index.ts */

import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import { createWrapper } from 'next-redux-wrapper';
import logger from 'redux-logger';

import reducer from './modules';

const makeStore = (context) =>
  configureStore({
    reducer,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
    devTools: process.env.NODE_ENV !== 'production',
  });

export const wrapper = createWrapper(makeStore, {
  debug: process.env.NODE_ENV !== 'production',
});

configureStore(): createStore 와 동일한 기능에 DevTools/Middleware 추가, 생성한 reducer까지 하나의 인자로 받음


/* src/store/modules/admin.ts */

import { createSlice } from '@reduxjs/toolkit';
import { IAdminInfo } from '../../../global-interfaces';

const initialState = {
  info: {
    authorization: '',
    nick: '',
    roleCd: '',
    statCd: '',
    userEmail: '',
    userId: '',
    userLevel: '',
  },
};
const adminSlice = createSlice({
  name: 'admin',
  initialState,
  reducers: {
    logout: (state) => {
      state.info = undefined;
    },
    login: (state, action) => {
      state.info = action.payload;
    },
  },
});

export const { login, logout } = adminSlice.actions;
export default adminSlice.reducer;

createSlice(): reducer이름과 함수가 포함된 초기 상태와 lookup테이블을 받아 액션 생성자 함수, 액션 유형 문자열 및 리듀서 함수를 자동으로 생성

/* src/store/modules/index.ts*/

import { combineReducers } from '@reduxjs/toolkit';
import { HYDRATE } from 'next-redux-wrapper';

import admin from './admin';

const reducer = (state, action) => {
  if (action.type === HYDRATE) {
    return {
      ...state,
      ...action.payload,
    };
  }
  return combineReducers({
    admin,
  })(state, action);
};

export default reducer;

hydrate : Next.js 서버에서 생성한 redux store와 client에서 생성한 redux store가 다르기 때문에, 이렇게 서버에서 생성한 store의 상태를 (HYDRATE라는 액션으로) client에 합쳐준다.

/* src/pages/_app.tsx */

import '../styles/globals.scss';
import Head from 'next/head';
import Router from 'next/router';
import React from 'react';
import { wrapper } from "../store";



function MyApp({ Component, pageProps }) {
  const Layout = Component.layout || (({ children }) => <>{children}</>);

  return (
    <React.Fragment>
      <Head>
        <meta name='viewport'
          content='width=device-width, initial-scale=1, shrink-to-fit=no'
        />
        <title>Admin Page</title>
      </Head>
      <Layout> <Component {...pageProps} /></Layout>
    </React.Fragment >)
    ;
}

export default wrapper.withRedux(MyApp);
profile
헌신하고 확장하는 삶
post-custom-banner

0개의 댓글