通过 redux-saga 调度动作时 React 应用程序冻结

React app freezes when dispatching an action through redux-saga

我正在尝试掌握 React 和 redux-saga,我遇到的问题是每当我尝试在功能组件的 useEffect 挂钩中调度任何状态更改操作时,例如,使用useDispatch hook,应用程序冻结。现在 useSelector 工作正常,我可以获取状态。

我试过阅读 redux-saga 文档关于应用程序冻结的故障排除部分,其中说你必须执行操作,但我已经这样做了:

import { put } from 'redux-saga/effects';

import * as actions from '../actions/index';

export function* globalLoadingSaga(action) {
  yield put(actions.setGlobalLoading());
}

我也试过去掉括号,即离开:

export function* globalLoadingSaga(action) {
  yield put(actions.setGlobalLoading);
}

它似乎可以工作,但我收到一个错误:“错误:操作必须是普通对象。使用自定义中间件进行异步操作。”而且,操作是普通对象:

export const setGlobalLoading = (loading) => {
  return {
    type: actionTypes.SET_GLOBAL_LOADING,
    loading: loading,
  };
};

所以这对我来说似乎不对。

我也尝试过使用“fork”而不是“put”,但它又给了我另一个错误“错误:fork:{context,fn} 类型的参数未定义或为空 fn”,再一次,我觉得这不对。

我尝试用谷歌搜索它,但找不到与此问题有点相似的内容,此时我迷路了。

最奇怪的是,我确实知道这样的实施以前曾完美无缺地工作过。我从几个月前通过在线课程创建的项目中获得了它。那时候一切都很好。出于好奇,我确实尝试打开那个项目,看看它是否有同样的问题,而且不知何故,应用程序也冻结了。我没有改变任何东西,从那以后甚至没有碰过它,没有更新任何依赖项,什么都没有,但应用程序仍然挂起。

这里是一个 codesandbox 片段,被剥离到最低限度,它也可能由于某种循环而冻结:https://codesandbox.io/s/jovial-kowalevski-dotvp?file=/src/index.js

您遇到调度 SET_GLOBAL_LOADING 操作类型的无限循环。

// App.js
const onSetGlobalLoading = useCallback(
  (boolean) => {
    dispatch(actions.setGlobalLoading(boolean)); // <-- Dispatches action type of 'SET_GLOBAL_LOADING'
  },
  [dispatch]
);

由于您从 App.js 发送了 SET_GLOBAL_LOADING 的动作类型,因此您有一个监听 SET_GLOBAL_LOADING 的动作类型的 saga。但是在那个传奇中,你还调度了一个 SET_GLOBAL_LOADING,这就是它执行无限循环的原因。

export function* globalLoadingSaga(action) {
  yield put(actions.setGlobalLoading()); // <-- Dispatches action type of 'SET_GLOBAL_LOADING', which is the reason your app freeze
}

所以答案可能是,您可以对您的 saga 发送不同的操作。