마지막으로 SSR을 위해 getserversideprops에서 store에 접근 할 수 있도록 redux-wrapper를 추가해줬다.
//store.ts
import { Action, configureStore, EnhancedStore, ThunkAction } from "@reduxjs/toolkit";
import { persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from "redux-persist";
import storage from "redux-persist/lib/storage";
import { combineReducers, Store } from "redux";
import counterReducer from "./slices/counterSlice";
import logger from "redux-logger";
import accountReducer from "./slices/accountSlice";
import { createWrapper, MakeStore } from "next-redux-wrapper";
const persistConfig = {
key: "root",
version: 1,
storage
};
const rootReducer = combineReducers({ counter: counterReducer, account: accountReducer });
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
middleware: getDefaultMiddleware =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
}
}).concat(logger),
devTools: process.env.NEXT_PUBLIC_NODE_ENV !== "production"
});
const setupStore = (context: any): EnhancedStore => store;
const makeStore: MakeStore<any> = (context: any) => setupStore(context);
export const persistor = persistStore(store);
export const wrapper = createWrapper<Store>(makeStore);
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, unknown, Action<string>>;
// _app.tsx
import "../styles/global.scss";
import type { AppProps } from "next/app";
import { store, wrapper } from "../features/store";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { persistor } from "../features/store";
function MyApp({ Component, pageProps }: AppProps) {
return (
<Provider store={store}>
<PersistGate persistor={persistor} loading={null}>
<Component {...pageProps} />
</PersistGate>
</Provider>
);
}
export default wrapper.withRedux(MyApp);
//index.ts
export const getServerSideProps = wrapper.getServerSideProps(store => async ({ req, res, ...etc }) => {
// store에 저장되어있는 state를 getState()를 써서 확인 할 수 있다.
store.getState().counter
return { props: {} };
});
wrapper까지 끝나면 환경설정은 마무리가 되는 것 같다.
안녕하세요, 글이 도움이 많이 되었습니다! 공부하다 어려움이 생겨 두 가지 질문을 여쭤보고자 합니다!
혹시 setupStore 함수와 makeStore 함수에 대해 알려주시거나 보고 이해할 수 있을 만한 자료를 추천해주실 수 있으실까요?? RTK 공식 문서의 persist 구성하는 부분엔 없는 코드 같아서요!
또한 redux-persist의 버전을 5나 6중에 어떤 것을 사용하셨나요? 저같은 경우는 6.0.0인데
"redux-persist failed to create sync storage. falling back to noop storage." 라는 문구가 터미널에 출력되더라구요! 혹시 같은 문제를 겪으셨나 싶어 여쭤봅니다.
감사합니다!
안녕하세요, 글 잘 읽어보았습니다.
선생님 근데 getServerSideProps에서 dispatch한 (wrapper기능) 값은 화면으로 어떻게 selector해서 가져오나요? getServerSideProps에서 dipatch는 모두 무시되는것 같습니다.
제가 기대한 결과는 서버사이드에서 디스패치한 스토어랑 합쳐질줄알았는데, 무시되어서 이전 화면에서 디스패치한 값을 들고있었습니다.
export const getServerSideProps = wrapper.getServerSideProps(
(store) =>
async ({ req, res, ...etc }) => {
// store에 저장되어있는 state를 getState()를 써서 확인 할 수 있다.
store.dispatch(login("power legendry")); <-- 무시됨 화면엔 빈 값
// console.log("testttttttttttttttt", store.getState().admin);
return { props: {} };
}
);
// 화면
const { userId } = useAppSelector((state) => state.admin); <-- 빈 값입니다.