리덕스 툴킷을 이용해 로그인/로그아웃 상태를 변경하는 데에는 성공했다.
그런데 페이지 새로고침을 할 때마다 강제 로그아웃이 되어서;
localStorage 또는 sessionStorage 에 Redux state를 저장하기 위한 redux-persist를 사용하게 되었다.
코드스테이츠에서 첫번째 프로젝트 할 때 사용했던 라이브러리라 익숙할 줄 알았는데 개뿔 ㅎㅎ Next.js 에서 쓰니까 넘나 새로운 빢침이었다.
persistReducer
와 persistStore
를 미리 세팅한 redux store와 reducer에 얹으면 된다고 한다.
우리가 병합하고 싶은 state의 레벨의 수를 결정하는 게 중요하다고 하네.
yarn add redux-persist
// store/index.ts
import rootReducer from './reducers';
import storage from 'redux-persist/lib/storage' // default: localStorage
persistConfig
에 storage와 key 값을 담는다.const persistConfig = {
key: 'root',
storage
persistConfig
를 적용한 리듀서를 만든다.const persistedReducer = persistReducer(persistConfig, rootReducer)
Q. PersistGate
로 root Component를 감싸줘야하는 이유
A. React를 사용한다면 써야하는데, 이유는 state를 조회한 후 리덕스에 저장할 때까지 웹 어플리케이션의 UI가 렌더링되는 것을 지연시켜야하기때문이다.
//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);
참고 자료
덕분에 구현 잘했습니다!ㅎㅎ 감사합니다