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;

 

반응형

 

반응형