RTK(Redux Toolkikt) + redux-persist 코드 적용

YEZI🎐·2023년 8월 3일
1

React

목록 보기
32/46

진짜 진짜 까먹을까봐 적는 RTK(Redux Toolkikt), Redux-persist

설치

# with npm
npm install @reduxjs/toolkit react-redux

# with yarn
yarn add @reduxjs/toolkit react-redux

폴더 구조

src
 │
 ├── store
 │   ├── store.ts			// 저장소
 │   ├── features			// 기능 폴더
 │   └───── authSlice.ts	// 기능 Slice
 ├── components
 │   ├── Profile.tsx
 │   └── ...
 main.tsx
 ...

RTK(Redux Toolkikt)

1. Reducer(Slice)를 만들어보자

/* authSlice.ts */

import { createSlice } from '@reduxjs/toolkit';	// reducer 만드는 걸 도와줌

const initialState = {		// 초기 상태
  nickname: '',
  email: '',
  accessToken: '',
  refreshToken: '',
};

export const authSlice = createSlice({	// name, initialState, reducers 필수 값
  name: 'auth',
  initialState: {
    value: initialState,
  },
  reducers: {	// state 변경 메소드들
    login: (state, action) => {
      state.value = { ...state.value, ...action.payload };
    },
    logout: (state) => {
      state.value = initialState;
    },
  },
});

export const { login, logout } = authSlice.actions;
export default authSlice.reducer;
// createSlice는 객체를 return 하고 return 된 값들 중 reducer를 export 해야 함

2. store.ts를 생성하여 저장소를 만들어준다

/* store.ts */
import { configureStore } from '@reduxjs/toolkit';
import authReducer from './features/auth/authSlice';

const store = configureStore({
  reducer: {
    auth: authReducer,	// 앞서 export 했던 reducer를 auth라는 이름으로 저장
  },
});

export default store;
export type RootState = ReturnType<typeof store.getState>;
// typescript 이기 때문에 RootState type을 export 해야 함

3. root로 가서 store 감싸기

/* main.tsx */
import ReactDOM from 'react-dom/client';
import './index.css';

import { RouterProvider } from 'react-router-dom';
import router from './routes/Router';

import { Provider } from 'react-redux';	// Provider import
import store from './store/store';		// store import

ReactDOM.createRoot(document.getElementById('root')!).render(
  <Provider store={store}>	// root를 Provider로 감싼 후 store 넘겨주기
    <RouterProvider router={router} />,
  </Provider>
);

4. 컴포넌트에서 사용하기

/* Profile.tsx */
import { useDispatch, useSelector } from 'react-redux';
// useDispatch : state 변경 메소드를 이용하여 store에 있는 state 변경
// useSelector : store에 있는 원하는 state 가져옴
import { type RootState } from '../store/store';
// 앞서 store.ts에서 export한 type import
import { logout } from '../store/features/authSlice';
// 앞서 authSlice.ts에서 export한 state 변경 메소드 import

export default function Profile() {
  const dispatch = useDispatch();
  const user = useSelector((state: RootState) => state.auth.value);

  return (
    <div>
      <p>nickname: {user.nickname}</p>
      <p>email: {user.email}</p>
      <button onClick={() => dispatch(logout())}>로그아웃</button>
    </div>
  );
}

redux-persist

store에 저장된 state를 storage에 저장하기 위해 redux-persist를 사용했다.
다들 RTK에 redux-persist을 적용하는 걸 너무 어렵게 설명해놨는데 진짜 별거 아님

위에서 작성한 store.ts에 아래 코드 중 주석 달린 부분만 추가해주면 됨

import { configureStore, combineReducers } from '@reduxjs/toolkit';
import authReducer from './features/authSlice';

import { persistReducer } from 'redux-persist';		// 추가
import storage from 'redux-persist/lib/storage';	// 추가, default : localStorage
// Session → import storageSession from 'redux-persist/lib/storage/session

const rootReducer = combineReducers({
  auth: authReducer,
});
// ↑ 추가 ❶
// store.ts에서 reducer에 작성했던 것들을 빼내어 combineReducers에 작성

const persistConfig = {
  key: 'auth',			// storage에 저장될 key 입력
  storage,				// 저장될 위치 입력
  whitelist: ['auth'],	// 저장할 state 입력
};
// ↑ 추가 ❷

const persistedReducer = persistReducer(persistConfig, rootReducer);
// ↑ 추가
// persistReducer에 앞서 작성한 ❶, ❷를 인자로 넘김

const store = configureStore({
  reducer: persistedReducer,
  // ↑ 수정
  // 앞서 작성한 persistedReducer로 값 수정
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false,
    }),
  // ↑ 에러 때문에 추가했음, 필수 아님
});

export default store;
export type RootState = ReturnType<typeof store.getState>;
profile
까먹지마도토도토잠보🐘

1개의 댓글

comment-user-thumbnail
2023년 8월 3일

이렇게 유용한 정보를 공유해주셔서 감사합니다.

답글 달기