그럼에도 불구하고

👨‍💻

[Redux with TS] 새로고침해도 redux store를 유지하는 법 본문

React/Redux

[Redux with TS] 새로고침해도 redux store를 유지하는 법

zenghyun 2023. 7. 25. 08:28

 

새로고침해도 redux의 store를 유지하는 법에 대해 알아보겠습니다.

 

 

🧑🏻‍💻 Redux-Persist

Redux는 새로고침하거나 창을 닫으면 store에 저장된 state가 리셋됩니다. 이를 방지하기 위해 Redux의 Redux-Persist를 사용해 보겠습니다. 

 

 

 

 

현재 Posts 상에 있는 게시물에서 View Post를 누르면 해당 게시물의 상세 페이지로 넘어가고 각각의 게시물마다 nanoid로 지정된 id를 통해 해당 페이지로 이동하고 있습니다. 

 

내 localhost/post/:nanoid

 

이때 생성된 nanoid는 무작위이며, 새로고침할 때마다 redux store는 기존 state를 가지고 있지 못하고 새로운 nanoid로 생성된 게시물 리스트를 갖고 있습니다. 

 

그렇기 때문에 기존 state가 존재하지 않아 Page not found!라는 문구가 나타나게 됩니다. 

 

 

이제는 Redux Persist를 이용하여 새로고침해도 store의 state를 유지시켜 보겠습니다.

 

⭐️  설치

우선 redux persist를 이용하기위해 터미널을 통해 다운로드하여야 합니다.

 

📌 npm
npm i redux-persist

📌 yarn
yarn add redux-persist

 

 

📌 store.ts

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { configureStore } from "@reduxjs/toolkit";
import postsReducer, { PostListsType } from "../features/posts/postsSlice";
import usersReducer, { UserListType } from "../features/users/usersSlice";
import { combineReducers } from "@reduxjs/toolkit";
import storage from 'redux-persist/lib/storage';
import { persistReducer } from "redux-persist";
 
export type RootStateType = {
  posts: PostListsType;
  users: UserListType;
};
const reducers = combineReducers({
  posts: postsReducer,
  users: usersReducer,
});
 
const persistConfig = {
  key: 'root'// localStorage key 
  storage, // localStorage
};
 
const persistedReducer = persistReducer(persistConfig, reducers);
 
export default configureStore({
  reducer: persistedReducer,
  middleware: getDefaultMiddleware => getDefaultMiddleware({ serializableCheck: false }),
});
 
cs

 

1. combineReducers로 Reducer 감싸기

 

2. persistConfig 작성하기 

 

const persistConfig = {
  key: 'root', // localStorage key 
  storage, // localStorage
  // whitelist: [""], // target (reducer name)
};

key는 localStorate의 key이며, storage는 localStorage를 의미합니다.

 

whitelist를 사용하면 특정 reducer만을 target으로 하여 state가 유지되도록 할 수 있습니다.

 

3. persistReducer 만들기

 

const persistedReducer = persistReducer(persistConfig, reducers);

 

4.  store에 결합하기

 

export default configureStore({
  reducer: persistedReducer,
  middleware: getDefaultMiddleware => getDefaultMiddleware({ serializableCheck: false }),
});

 

여기서 serializableCheck를 false를 하는 이유는 Redux는 state, action에 직렬화가 불가능한 값을 전달할 수 없기 때문에 이를 방지하고자 기본값인 true를 false로 지정한 것입니다. 

 

 

📌 main.tsx

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import { Provider } from 'react-redux'
import store from './app/store.ts'
import { worker } from "./api/server.js";
import { fetchUsers } from './features/users/usersSlice.ts'
import persistStore from 'redux-persist/es/persistStore'
import { PersistGate } from 'redux-persist/integration/react'
 
if (process.env.NODE_ENV === "development") {
  worker.start();
  store.dispatch(fetchUsers());
}
 
const persistor = persistStore(store);
 
ReactDOM.createRoot(document.getElementById('root')!).render(
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
    <App />
      </PersistGate>
    </Provider>
)
 
cs

 

persistStore에 기존 store를 인자로 넣어주고 그 값을 PersistGate에 선언해 주면 됩니다. :)

 

 

 

🏷️ ref 

https://edvins.io/how-to-use-redux-persist-with-redux-toolkit

 

How to use Redux-Persist with Redux-Toolkit

Redux Toolkit is the official, opinionated, batteries-included toolset for efficient Redux development. It's intended to be the standard way to write Redux logic.

edvins.io

 

Comments