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

React Query useMutation重复调用求助:MQTT触发API调用次数递增

问题原因分析

你的问题核心是MQTT事件监听重复绑定,导致每条消息触发多次API调用:

  1. 组件每次渲染时,顶层的mqtt.connect会创建新的Client实例,useEffect依赖client变化,会重复执行并绑定新的connect/message监听
  2. handleRfidCard函数每次渲染都会重新创建,导致useEffect依赖变化,进一步触发重复绑定
  3. 旧的监听没有被清理,叠加后每条消息会触发所有已绑定的监听,API调用次数随之递增
解决方案

1. 用useRef保存MQTT Client实例

确保整个组件生命周期内只有一个Client,避免重复创建和连接:

import { useRef, useEffect, useCallback } from 'react';
import mqtt from 'mqtt';

// ...组件其他代码

const clientRef = useRef<mqtt.MqttClient | null>(null);

useEffect(() => {
  // 仅初始化一次Client
  if (!clientRef.current) {
    clientRef.current = mqtt.connect(brokerUrl, {
      clientId,
      clean: true,
      username: import.meta.env.VITE_MQTT_BROKER_USERNAME,
      password: import.meta.env.VITE_MQTT_BROKER_PASSWORD,
    });
  }
  const client = clientRef.current;

  // 单独定义事件处理函数,方便后续清理
  const handleConnect = () => {
    client.subscribe("rfid", () => {});
  };

  const handleMessage = (topic: string, message: Buffer) => {
    if (topic === "rfid") {
      handleRfidCard(message.toString());
    }
  };

  // 绑定监听
  client.on("connect", handleConnect);
  client.on("message", handleMessage);

  // 清理函数:移除监听,避免内存泄漏和重复触发
  return () => {
    client.off("connect", handleConnect);
    client.off("message", handleMessage);
    // 组件卸载时可选断开连接
    // client.end();
  };
}, [handleRfidCard]); // 仅依赖稳定后的handleRfidCard

2. 用useCallback稳定handleRfidCard引用

避免函数每次渲染重新创建,导致useEffect重复执行:

const handleRfidCard = useCallback((rfidID: string) => {
  if (rfidID) {
    rfidCard.mutate(rfidID, {
      onSuccess: (data) => {
        capture(data.id, data.type);
      },
    });
    rfidHistory.mutate(rfidID);
  }
}, [rfidCard, rfidHistory, capture]); // 依赖对应的mutation和capture函数

3. 额外检查:确保clientId稳定

如果clientId是动态生成的(比如每次渲染都生成新ID),会导致MQTT重复创建连接,需确保clientId在组件生命周期内唯一且稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:03:13