Next.jsにRedux/Redux-Sagaを導入する

Reduxまわりの構築をすぐ忘れてしまうのでここに書いておく

構成

├── modules
│   ├── <module name>
│   │    ├── reducers.ts
│   │    ├── hooks.ts
│   │    └── actions.ts
│   ├── creatersToActions.ts
│   └── store.ts
└── pages
   └── _app.tsx

Providerに渡すstoreの処理を作っていく
Redux-Sagaを入れるのにプラスしてデバッグ環境も整える。
Reactのデバッグをするときは、ChromeのExtensionを使用するのが一般的なので、redux-devtools-extensionに合わせて作る。
それに加えて本題のRedux-SagaをcreateStoreをする時に、ミドルウェアとしてかましてあげる
store.ts

import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import createSagaMiddleware from 'redux-saga';

const reducers = combineReducers({
  // 追加したいモジュールはここに書く
});

export type StoreState = ReturnType<typeof reducers>;

// Windowの型を拡張する
interface ExtendedWindow extends Window {
  __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
}
declare let window: ExtendedWindow;

// Redux DevTools用のEnhancers
const composeEnhancers = (() => {
  return (typeof window != 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
})();

const rootReducer = (state: any, action: any) => {
  if (action?.type === '_TEST_RESET_ALL_STORE') {
    state = undefined;
  }
  return reducers(state, action);
};

const sagaMiddleware = createSagaMiddleware();

export const store = createStore(rootReducer, composeEnhancers(applyMiddleware(sagaMiddleware)));

export const storeDispatch = (action: any) => {
  return store.dispatch(action);
};

_app.tsx

import React from 'react';
import App from 'next/app'
import { Provider } from 'react-redux';
import { store } from '../modules/store';

export default class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;
    return (
      <Provider store={store}>
        <Component {...pageProps} />
      </Provider>
    );
  }
}

こんな感じ。Context APIとHooks APIでReduxの疑実装も最近情報が安定してきた印象。モジュール化してしまえばあれもかなり役立つものになる。ただ、Reduxとそもそものコンセプトというものも違っているので両方知識として持っておいて使えるようになっておくのが一番かなと思う。

ReactHooks + Context API によるReduxの実装

関連記事