Next.js
NextJS + Redux-Toolkit + next-redux-wrapper 설정하기
Kir93
2021. 9. 24. 18:33
728x90
반응형
해당 글은 next-redux-wrapper@7 버전을 기반으로 작성되었습니다.
해당 방법은 필자 개인이 설정한 방법으로 언제든 더 좋은 방법이 있다면 공유해주시기 바랍니다.
NextJS의 큰 장점 중 하나인 SSR을 사용할 때 조금 더 편하게 사용하기 위해 next-redux-wrapper를 이용하여 dispatch를 사용할 수 있게 된다.
// testReducer.ts
export const initialState = {
// ...states
}
export type TestReducerState = typeof initialState;
const testSlice = createSlice({
name: 'user',
initialState,
reducers: {},
extraReducers: (builder) =>
// anyExtraReducers...
});
export default testSlice;
위와 같은 reduser를 test1, test2로 만들었다고 가정하고 진행하려고 한다.
toolkit의 사용법의 경우 다음에 다뤄보도록 하겠다.
// reducer.ts
import { AnyAction, CombinedState, combineReducers } from 'redux';
import { HYDRATE } from 'next-redux-wrapper';
import test1Slice, { Test1ReducerState } from './test1';
import test2Slice, { Test2ReducerState } from './test2';
export interface IState {
test1: Test1ReducerState;
test2: Test2ReducerState;
}
const rootReducer = (state: IState, action: AnyAction): CombinedState<IState> => {
switch (action.type) {
case HYDRATE:
return action.payload;
default: {
const combinedReducer = combineReducers({
user: userSlice.reducer,
post: postSlice.reducer,
});
return combinedReducer(state, action);
}
}
};
export default rootReducer;
위와 같이 만들어 놓은 reducer들을 합치는 것은 동일하지만 HYDRATE를 이용하여 SSR상태를 잡아준다.
// configureStore.ts
import { configureStore } from '@reduxjs/toolkit';
import { createWrapper } from 'next-redux-wrapper';
import rootReducer, { IState } from '@reducers/index';
import { Reducer, AnyAction } from 'redux';
const isDev = process.env.NODE_ENV === 'development';
const createStore = () => {
const store = configureStore({
reducer: rootReducer as Reducer<IState, AnyAction>,
devTools: isDev,
});
return store;
};
const wrapper = createWrapper(createStore);
export default wrapper;
이제 스토어를 생성한다.
나의 경우 rootReducer와 configureStore의 reducer의 Type문제로 고생했는데 강제로 상태를 정의해주는 방법을 이용했다.
본래라면 Provider를 이용해 store를 넘겨주겠지만, 우리는 next-redux-wrapper를 사용하니 createWrapper를 이용해 생성한 store를 감싸준다.
그리고 아래와 같이 마지막으로 Provider가 아닌 생성한 wrapper를 이용해 App를 감싸주면 사용할 준비가 끝난다.
import React from 'react';
import Head from 'next/head';
import { AppProps } from 'next/app';
import wrapper from '@utils/configureStore';
const App = ({ Component, pageProps }: AppProps): React.ReactElement => (
<>
<Head>
<title>Test</title>
</Head>
<Component {...pageProps} />
</>
);
export default wrapper.withRedux(App);
이제 아래와 같이 page들에서 SSR로 redux를 사용할 수 있다.
import React from 'react';
import wrapper from '@utils/configureStore';
import { loadTesting } from '@APIs/post';
const Index = (): React.ReactElement => (
<>
Index!!!
</>
);
export const getServerSideProps = wrapper.getServerSideProps((store) => async ({req,res, ...ets}) => {
// ({req, res, ...ets})는 ()로 생략해도 무관
await store.dispatch(loadTesting(10));
return { props: {} };
});
export default Index;
반응형