(21.07.30) redux-persist 사용하기
도깨비젤리
·2021. 7. 30. 17:53
작은 지식이라도, 하루에 하나씩.
한 줄 요약
🦄redux-persist는 redux의 state를 로컬/세션 스토리지에 저장하도록 하는 라이브러리🦄
🦄persist를 사용하기 위해서는 store를 persistedReducer로 만든 리듀서로 만들고, persistStore라는 함수로 store를 감싼 후, store를 **export** 해줘야한다.🦄
persist를 이용하기 위한 store 셋팅
// store를 모아서 통합하는 index.ts
import { combineReducers, createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import { persistReducer, persistStore } from "redux-persist";
import storage from "redux-persist/lib/storage";
import clientLogin from "./clientLogin";
const persistConfig = {
key: "root",
storage,
whitelist: ["clientLogin"], // required인지 모르겠당..
};
export const rootReducer = combineReducers({ clientLogin: clientLogin });
const persistedReducer = persistReducer(persistConfig, rootReducer);
export default function configureStore() {
const store = createStore(persistedReducer, composeWithDevTools());
const persistor = persistStore(store);
return { store, persistor };
}
여기서 whitelist는 로컬 스토리지에 저장할 리듀서를 지정하는 곳이다. 저길 생략하면 모든 리듀서가 로컬스토리지에 저장된다.
이 config와 persistedReucer를 사용해 redux-persist화 된 리듀서를 만들어줍니다.
이후, createStore를 이용해, persistedReducer로 스토어를 만들어주고, persistor라는 것을 persistStore를 통해 만들어줍니다
나중에 나오겠지만, persistor는 스토리지와 redux를 동기화 시키는 역할을 한다고 합니다. (<-- 긁어모은 지식이라 확실하지는 않습니다.)
//index.tsx (루트 컴포넌트)
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import TestCompo from "@components/TestCompo";
import configureStore from "./modules/index";
const { store, persistor } = configureStore();
const Root = () => (
<Provider store={store}>
<PersistGate loading={<TestCompo />} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
이후 루트 컴포넌트로 이동하여, 루트를 provider 안에 PersistGate라는 컴포넌트로 감싸줍니다.
여기서 loading props는 리덕스와 스토리지가 동기화 될 동안 표시될 컴포넌트를 지정하는 것이고, persistor 자리에는
위에서 제작한 perisist화 된 스토어와 persitor를 불러와서 사용해야합니다.
원래 저는 이 index.tsx 에서 스토어와 reducer를 perisist화 하였는데, 그렇게 하니 화면에 계속 loading 컴포넌트만 랜더링 되고, <App/>이 랜더링 되지 않는 일이 발생했습니다.
근데, 외부에서 스토어와 reducer를 perisist화 한 다음 import 하니, 아무런 문제 없이 잘 되는 겁니다.
왜 이런 기묘한 문제가 일어났는지 여러방면으로 수소문 할 결과, 리액트가 스토어를 인식하지 못해서라고 하는것 같다고 합니다.
redux-persist를 사용해본 코치님들의 코드를 보면서 같이 고민해봤는데, 코치님은 처음의 저 처럼 루트 컴포넌트 자체에서 perisist 화 하여도 에러가 나질 않았습니다.
저와 다른 점은 단 하나, createStore로 만든 store를 export 해줬다는 것입니다.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import TestCompo from "@components/TestCompo";
import { composeWithDevTools } from "redux-devtools-extension";
import rootReducer from "./modules/index";
import { createStore } from "redux";
import { persistStore } from "redux-persist";
const store = createStore(rootReducer, composeWithDevTools());
const persistor = persistStore(store);
// //여기서도 export를 해줬어야한다.
export store
const Root = () => (
<Provider store={store}>
<PersistGate loading={<TestCompo />} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
ReactDOM.render(<Root />, document.getElementById("root"));
대충 이런 느낌이였는데, 이렇게 스토어를 export 해주니 잘 돌아갔다는 말씀을 하셨습니다.
게다가, 확신하지는 못하지만, 아마도 export를 해주지 않아 PersistGate가 스토어를 읽어들이지 못해서 loading 컴포넌트만 계속 랜더링 하고 있는게 아닌라는 추론을 해주셨습니다.
듣고보니 상당히 일리있는 것 같습니다.
여하튼, 좀 더 실험을 해봐야겠지만, redux-persist를 사용할 때는 스토어가 export 되었는지를 꼭 확인해야겠고, 가급적이면 루트 컴포넌트 파일 외부에서, 스토어를 완성하여 가져오는 편이 정신건강에 좋을 것 같습니다.
'TIL' 카테고리의 다른 글
(21.08.02) Typescript에서 React Props를 받기 / React에서 배열 랜더링 (0) | 2021.08.02 |
---|---|
(21.08.01) SweetAlert2 (0) | 2021.08.01 |
(21.07.27) material-ui 스타일 && react-router-dom with TS (0) | 2021.07.27 |
(21.07.21) JS 구조분해 할당 && terminal과 shell의 차이 (2) | 2021.07.21 |
(21.07.21) React && firebase로 클론 코딩 완료 (0) | 2021.07.21 |