通过 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 发送不同的操作。
我正在尝试掌握 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 发送不同的操作。