You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redux-Toolkit中间件因API错误陷入无限循环问题求助

Redux-Toolkit中间件无限循环问题排查与解决

问题背景

在React项目中使用Redux-Toolkit做状态管理,编写了一个中间件用于在payload到达reducer前修改数据。中间件内调用翻译API将文本转为西班牙语,发现API出错时,中间件陷入无限循环。

相关代码

中间件代码

import { getSpanishText } from "../../helpers/storeSpanishText";

export const kioskSettingsMiddleware = (store) => (next) => async (action) => {
    const actionType = action.type;
    if (actionType === "kisokSettings/saveKioskPortalSettings") {
      const prevState = store.getState().kioskSettings;
      const data = action.payload;
      let settingObject = {
        autoDisconnect: data.auto_hang_up_call,
        multiPMS: data?.is_multi_pms_mapping,
      };

      if (
        data?.is_complete_operation_message &&
        data?.complete_operation_message !== prevState?.completeMessage
      ) {
        settingObject["completeMessage"] = data?.complete_operation_message;
        settingObject["EScompleteMessage"] = await getSpanishText(
          "EScompleteMessage",
          data?.complete_operation_message
        );
      }
   
      return store.dispatch({ type: actionType, payload: settingObject });
    }
    return next(action);
}

API调用代码

export const getSpanishText = (key, msg) => {
  return axios
    .get(`https://translation.googleapis.com/language/translate/v2`, {
      params: {
        key: TRANSLATE_API_KEY,
        q: msg,
        target: "es",
      },
    })
    .then((res) => {
      if (res.status === 200) {
        ipcRenderer.send("logs", {
          type: "info",
          msg: `ES TRANSLATION- [${key} : ${res.data.data.translations[0].translatedText}]`,
        });
        return res.data.data.translations[0].translatedText;
      }
    })
    .catch((err) => {
      ipcRenderer.send("logs", {
        type: "info",
        msg: `FALLBACK EN - [${key} : ${msg}]`,
      });
      return msg;
    });
};

问题根源

无限循环的核心原因是:中间件拦截到目标action后,没有通过next函数传递修改后的action,而是调用store.dispatch重新发送了同一个类型的action。这会导致中间件再次捕获到该action,重复执行修改逻辑并再次dispatch,形成闭环。

注:该循环与API是否出错无关——哪怕API调用成功,只要使用store.dispatch发送同类型action,就会触发无限循环。

解决方案

修改中间件逻辑,将store.dispatch替换为next函数,直接将修改后的action传递给下一个中间件或reducer,避免重新触发整个中间件链。

修改后的中间件代码:

import { getSpanishText } from "../../helpers/storeSpanishText";

export const kioskSettingsMiddleware = (store) => (next) => async (action) => {
    const actionType = action.type;
    if (actionType === "kisokSettings/saveKioskPortalSettings") {
      const prevState = store.getState().kioskSettings;
      const data = action.payload;
      let settingObject = {
        autoDisconnect: data.auto_hang_up_call,
        multiPMS: data?.is_multi_pms_mapping,
      };

      if (
        data?.is_complete_operation_message &&
        data?.complete_operation_message !== prevState?.completeMessage
      ) {
        settingObject["completeMessage"] = data?.complete_operation_message;
        settingObject["EScompleteMessage"] = await getSpanishText(
          "EScompleteMessage",
          data?.complete_operation_message
        );
      }
   
      // 使用next传递修改后的action,而非重新dispatch
      return next({ type: actionType, payload: settingObject });
    }
    return next(action);
}

额外说明

  • next函数是Redux中间件链的关键,它负责将action传递给后续的中间件或最终的reducer,不会重新触发整个拦截流程。
  • 异步逻辑(如API调用)在中间件中使用async/await是合法的,Redux-Toolkit支持异步中间件,只要确保最终通过next传递action即可。

内容的提问来源于stack exchange,提问作者Tushar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 17:15:00