web-dev-qa-db-ja.com

ReduxSagaホットリロード

私はReact&Reduxプロジェクトに取り組んでいました。このプロジェクトは、webpack-dev-middlewareとホットミドルウェアを使用してホットリロードするために使用されていました。

プロジェクトにReduxSagaを追加し、reduxストアにsagaミドルウェアを追加した後。サガコードを変更するたびに、ホットリロードが壊れてエラーメッセージが表示されるようです。

Provider>は、オンザフライでのstoreの変更をサポートしていません。 Redux2.xおよびReact Redux 2.xに更新したため、このエラーが発生する可能性が最も高くなります。これにより、リデューサーが自動的にホットリロードされなくなります。 https:// github移行手順については、.com/reactjs/react-redux/releases/tag/v2.0. を参照してください。

佐賀はジェネレーターを使用していて、時間に依存していることを理解しています。 Sagasでページをホットリロードすることは可能ですか? Reduxレデューサーがホットリロード中にそれ自体を置き換える方法と同じです。

ありがとう!

20
Kevin He

私はreduxとredux-sagaを使ったプロジェクトに取り組んでいます(しかし反応しません)。 sagaMiddleware.run()を使用してsagasのホットリロードを実装しましたが、提供したリンク( https://github.com/reactjs/react)に示されているように、モジュールのリロードを処理し、レデューサーとsagasを置き換える必要があります。 -redux/releases/tag/v2.0. )。

_import { createStore } from 'redux';
import rootReducer from '../reducers/index';
import getSagas from '../sagas';

export default function configureStore(initialState) {
  const sagaMiddleware = createSagaMiddleware()
  const store = createStore(rootReducer, initialState, applyMiddleware(sagaMiddleware));
  let sagaTask = sagaMiddleware.run(function* () {
     yield getSagas()
  })
  if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../reducers', () => {
      const nextRootReducer = require('../reducers/index');
      store.replaceReducer(nextRootReducer);
    });
    module.hot.accept('../sagas', () => {
      const getNewSagas = require('../sagas');
      sagaTask.cancel()
      sagaTask.done.then(() => {
        sagaTask = sagaMiddleware.run(function* replacedSaga (action) {
          yield getNewSagas()
        })
      })
    })
  }

  return store;
}
_

注意すべき重要なことは、getSagas()関数です。新しく作成されたsagasのジェネレータオブジェクトの配列を返します。すでに実行されているsagasから配列内に事前に作成されたオブジェクトを含めることはできません。この配列を1つのモジュールでのみ構築する場合は、定数配列を直接使用できますが、異なるモジュールからのsagaを構成して構築する場合は、必ずすべてのモジュールからsagaを再作成する必要があるため、すべてのモジュールが作成をエクスポートすることをお勧めします。固定のサガまたはサガの配列をエクスポートする代わりに機能します。たとえば、次のような関数である可能性があります。

_export default () => [
  takeEvery(SOME_ACTION, someActionSaga),
  takeEvery(OTHER_ACTION, otherActionSaga),
]
_

明らかに、すべてのサガは最初から再開され、内部状態のある複雑なサガがある場合は、現在の状態が失われます。

非常によく似たアプローチは、sagaMidleware.run()を呼び出す代わりに動的なサガを使用することです。これは非常によく似たソリューションですが、サガのサブセットをリロードして、さまざまな方法で処理できます。詳細については、 https://Gist.github.com/mpolci/f44635dc761955730f8479b271151cf2 を参照してください。

30
mpolci

バージョン_redux-saga_以降の_1.0.0_パッケージの更新:

@mpolciソリューションを使用して変更するだけ

sagaTask.done.then(() => {

sagaTask.toPromise().then(() => {

そして、すべてが同じように機能し始めます。

タスク ドキュメントを参照してください

5
eMko