Redux-persist + Next Redux Wrapper 사용하기

devPomme·2021년 11월 17일
9

Next.js + Redux

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

리덕스 툴킷을 이용해 로그인/로그아웃 상태를 변경하는 데에는 성공했다.
그런데 페이지 새로고침을 할 때마다 강제 로그아웃이 되어서;
localStorage 또는 sessionStorage 에 Redux state를 저장하기 위한 redux-persist를 사용하게 되었다.
코드스테이츠에서 첫번째 프로젝트 할 때 사용했던 라이브러리라 익숙할 줄 알았는데 개뿔 ㅎㅎ Next.js 에서 쓰니까 넘나 새로운 빢침이었다.

Redux+Persist

동작 원리

persistReducerpersistStore 를 미리 세팅한 redux store와 reducer에 얹으면 된다고 한다.
우리가 병합하고 싶은 state의 레벨의 수를 결정하는 게 중요하다고 하네.

yarn add redux-persist

사용 방법

  1. 기존에 만들어놓은 리듀서를 준비한다.
// store/index.ts
import rootReducer from './reducers';
import storage from 'redux-persist/lib/storage'  // default: localStorage
  1. persistConfig에 storage와 key 값을 담는다.
const persistConfig = {
  key: 'root',
  storage
  
  1. 기존에 만들어놓은 리듀서에 persist에 대한 설정을 담은 persistConfig를 적용한 리듀서를 만든다.
const persistedReducer = persistReducer(persistConfig, rootReducer)
  1. persistStore를 생성한다.

Q. PersistGate로 root Component를 감싸줘야하는 이유
A. React를 사용한다면 써야하는데, 이유는 state를 조회한 후 리덕스에 저장할 때까지 웹 어플리케이션의 UI가 렌더링되는 것을 지연시켜야하기때문이다.

Next-Redux-Wrapper

//src/store/index.ts

import { applyMiddleware, createStore, compose } from 'redux';
import { createWrapper } from 'next-redux-wrapper';
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from 'redux-logger';
import { rootReducer, persistedReducer } from './modules';
import { persistStore, persistReducer } from 'redux-persist';

// server-side 스토어와 client-side store를 합쳐준다.

const makeConfiguredStore = (reducer) => createStore(reducer, undefined, applyMiddleware(logger));
const makeStore = () => {
  const isServer = typeof window === 'undefined';

  if (isServer) {
    return makeConfiguredStore(rootReducer);
  } else {
    // we need it only on client side
    const store = makeConfiguredStore(persistedReducer);
    let persistor = persistStore(store);
    return { persistor, ...store };
  }
};

// wrapper 로 감싸기
export const wrapper = createWrapper(makeStore, {
  debug: process.env.NODE_ENV !== 'production',
});
// src/pages/_App.tsx
import React, { Component } from 'react';
import { wrapper } from '../store';
import { createStore } from 'redux';
import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react';
import {  persistedReducer } from 'store/modules';


function MyApp({ Component, pageProps }) {
  const Layout = Component.layout || (({ children }) => <>{children}</>);
  const store = createStore(persistedReducer);
  const persistor = persistStore(store);
  return (
    <PersistGate persistor={persistor} loading={<div>loading...</div>}>
      <React.Fragment>
        <Head>
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
          <title>Coala Admin</title>
        </Head>
        <Layout>
          <Component {...pageProps} />
        </Layout>
      </React.Fragment>
    </PersistGate>
  );
}

export default wrapper.withRedux(MyApp);

참고 자료

profile
헌신하고 확장하는 삶
post-custom-banner

2개의 댓글

comment-user-thumbnail
2021년 12월 2일

덕분에 구현 잘했습니다!ㅎㅎ 감사합니다

답글 달기
comment-user-thumbnail
2022년 10월 25일

Next.js - Redux-Toolkit - Redux-Persist 조합으로 환경설정 하는게 막막했는데 덕분에 하나하나 따라하니 정상적으로 구현이 됐습니다.

감사합니다!

답글 달기