5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ReduxのreducerもHot Reloadingさせる方法

Posted at

はじめに

WebpackReact Hot Loaderを使うことでReactコンポーネントのHot Reloadingができるが、Reduxを使った場合にreducerのHot Reloadingにはコツが必要だったので書いておく。また、TypeScriptを使って書く場合には追加で注意事項もあるので合わせて書いておく。

前提

React Hot Loaderは現在v3系が開発中だが、今回は2016/06/20時点で安定版の v1.3.0 で動作確認している。動作確認はしていないが、v3系でも同様の方法でいけるはず。

方法

ReduxのcreateStoreを呼んでStoreを作成している箇所に、Hot Reloading用のコードを入れる必要がある。

通常の書き方
import { createStore } from 'redux';
import rootReducer from '../reducers';

export default function configureStore(initialState) {
  return createStore(rootReducer, initialState);
}
Hot Reloadingさせる書き方
export default function configureStore(initialState) {
  const store = createStore(rootReducer, initialState, enhancer);

  if (module.hot) {
    module.hot.accept('../reducers', () =>
      store.replaceReducer(require('../reducers').default)
    );
  }

  return store;
}

※reducerモジュールのパス ../reducers は適宜アプリケーション構成に合わせて修正すること

TypeScriptで書く場合の注意点

自分はTypeScriptで書いていて見事にハマったので書いておく。

何も考えずにmodule.hotと書くとTypeScriptがエラーを吐いてしまうので、最初以下の様に書いて回避していたのだが、これだとHot Reloadingが動作せず困っていた。

駄目な書き方
export default function configureStore(initialState) {
  const store = createStore(rootReducer, initialState, enhancer);

  if (module['hot']) {
    module['hot'].accept('../reducers', () =>
      store.replaceReducer(require('../reducers').default)
    );
  }

  return store;
}

Hot Reloadingのコードをデバッグしてみたところ、acceptで渡される引数が../reducersのままで渡っていた。JavaScriptで動作する環境で確認すると、ここはモジュール名ではなく数値のモジュールIDが渡ってきていた。
ここでmodule.hot.acceptでないとWebpackがうまく変換できないのだろう、と推測。

というわけで、下記のように一旦declare var module: anyを宣言してmodule.hot.acceptと書けるように変更したところ、無事に動作するようになった。

OKな書き方
declare var module: any;

export default function configureStore(initialState) {
  const store = createStore(rootReducer, initialState, enhancer);

  if (module.hot) {
    module.hot.accept('../reducers', () =>
      store.replaceReducer(require('../reducers').default)
    );
  }

  return store;
}

というわけで、module.hot.acceptと書かなければならないので注意しよう。

参考

redux reducer hot reloading などでググると以下のIssueコメントにたどりついた。ここで作者のDanさんがreducerのHot Reloading方法について説明していた。

Starter Kits

React Hot Loader で紹介されているStarter Kits 一覧 には、ReduxでHot Reloadingを組み込んだものとして2つ紹介されている。ともに下記の箇所でReducerのHot Reloadingにも対応するためのコードが入れられている。これらのStarter Kitsを使っておけば大丈夫。

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?