애드블럭 종료 후 보실 수 있습니다.

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NextJS + Redux-Toolkit + next-redux-wrapper 설정하기
    Next.js 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;

     

     

    댓글

Designed by Tistory.