如何从 redux-observables 中的史诗访问调度功能

How to access dispatch function from epic in redux-observables

我想知道是否可以从 redux-observables (1.2) 中的史诗访问 redux 的 dispatch 函数。

export const epicDownloadProfile = (action$, { dispatch }) =>
  action$.pipe(
    ofType(DOWNLOAD_INIT.getType()),
    switchMap(() =>
      from(downloadStart(dispatch)).pipe(
        map(() => DOWNLOAD_INIT()),
        catchError(err => of(DOWNLOAD_ERROR.asError(err.message)))
      )
    )
  )

我知道这并不理想,但我有一个非常复杂的函数,在下载时会生成很多东西,所以我需要将 dispatch 传递给 downloadStart()。 Redux-observables 给我提供了一个 StateObservable object 作为史诗的第二个参数,它确实包含状态,但不包含调度函数...在示例中 { dispatch }来了undefined。还有其他方法可以访问它吗?

您确实提到这并不理想,但对于可能没有阅读您的问题的其他人,我必须添加一个警告,即这样做暗示您可能正在做的是 anti-pattern-- 但不是总是!当然,如果您正在使用某种您无法控制的第三方库,并且您需要将其传递给它,那么这是一个可以理解的解决方法。只是不要太想一直在 Epics 周围打电话给 store.dispatch(),因为这通常是您正在与 redux-observable 战斗的迹象。当然,归根结底,这只是建议嘿嘿:)

好的。因此,您可以这样做:

redux-observable 提供了一种将依赖项注入每个史诗的方法。因此,当您创建 epicMiddleware 时,您可以传递对商店、调度或其他任何内容的引用。

https://redux-observable.js.org/docs/recipes/InjectingDependenciesIntoEpics.html

/* Where ever you create your store/middleware
*****************************************/
const middlewares = [];
const epicMiddleware = createEpicMiddleware({
  dependencies: {
    get store() { // or getStore() if you want
      return store;
    }
  }
});

middlewares.push(applyMiddleware(epicMiddleware));

const store = createStore(
  rootReducer,
  initialState,
  composeEnhancers(...middlewares)
);

epicMiddleware.run(rootEpic);

/* Where ever this epic is
*************************/
const epicDownloadProfile = (action$, state$, { store }) =>
  action$.pipe(                  dependencies ----^
    ofType(DOWNLOAD_INIT.getType()),
    switchMap(() =>
      from(downloadStart(store.dispatch)).pipe(
        map(() => DOWNLOAD_INIT()),
        catchError((err) => of(DOWNLOAD_ERROR.asError(err.message)))
      )
    )
  );

还有其他方法,例如从模块中导出您的商店,将其导入到您的史诗模块中。但如果你需要不想让你的商店成为单身人士,做SSR等,那可能不太好

这是另一种方法,如果您愿意的话,因为无论如何您都应该在创建商店之后启动根史诗。

// Manually inject it yourself by wrapping the "root epic"
// with another function, which is basically an epic which
// defers to your root epic.
epicMiddleware.run((action$, state$) => {
  return rootEpic(action$, state$, { store });
});