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

React项目集成FCM SDK 9后前后台均重复接收通知问题求解

问题原因

你遇到的重复通知问题是多个代码错误叠加导致的,核心问题如下:

  1. App.js中FCM消息监听器重复注册:你没有把监听器放在useEffect中,每次组件重渲染都会新增一个监听器,收到消息时所有注册的回调都会触发,弹出多个通知
  2. onMessageListener的实现逻辑错误:你将持续触发的onMessage事件包装成了仅能resolve一次的Promise,不但会导致后续消息无法正常接收,还会随着组件渲染生成大量无用的监听器
  3. Service Worker代码存在API调用错误:showNotification第一个参数是通知标题,你直接传入了配置对象,调用失败后FCM SDK会触发兜底的默认通知,和你期望的自定义通知叠加
  4. Service Worker未完成Firebase初始化:你在sw代码中仅引入了initializeApp但没有调用,会导致FCM SDK逻辑异常
  5. 额外监听器重复注册:你引入的Notifications组件可能也注册了FCM消息监听器,导致同一消息触发多次回调

修复步骤

1. 修正firebaseInit中的消息监听逻辑

不要将onMessage包装为Promise,改为返回可取消的监听函数:

// firebaseInit.js 替换原有onMessageListener实现
export const listenForForegroundMessages = (callback) => {
  return onMessage(messaging, (payload) => {
    console.log('前台收到消息', payload);
    callback(payload);
  });
};

2. 修正App.js中的监听器注册逻辑

用useEffect包裹监听器注册,添加卸载时的清理逻辑,避免重复注册:

// App.js 替换原有监听逻辑
import React, {useState, useEffect} from "react";
import {listenForForegroundMessages} from "./firebaseInit";

function App() {
    const [show, setShow] = useState(false);
    const [notification, setNotification] = useState({title: "", body: ""});    

    useEffect(() => {
      // 注册监听器
      const unsubscribe = listenForForegroundMessages((payload) => {
        setShow(true);
        setNotification({
          title: payload.data.title,
          body: payload.data.body,
        });
      });
      // 组件卸载时清理监听器
      return () => unsubscribe();
    }, []);

    // 剩余原有代码不变
}

3. 修正Service Worker代码

补全Firebase初始化,修正showNotification的传参错误:

// firebase-messaging-sw.js
import { initializeApp } from "firebase/app";
import { getMessaging } from "firebase/messaging";
import { onBackgroundMessage } from "firebase/messaging/sw";

// 复制你的firebase配置到这里
const firebaseConfig = {
    apiKey: "mykey",
    authDomain: "mykey",
    projectId: "mykey",
    storageBucket: "mykey",
    messagingSenderId: "mykey",
    appId: "mykey",
    measurementId: "mykey"
};
// 初始化Firebase
initializeApp(firebaseConfig);
const messaging = getMessaging();

onBackgroundMessage(messaging, (payload) => {
    console.log('后台收到消息', payload);
    const notificationOptions = {
        body: payload.data.body,
        icon: "/logo192.png",
    };
    // 修正传参:第一个参数为通知标题,第二个为配置项
    return self.registration.showNotification(payload.data.title, notificationOptions);
});

4. 移除多余监听器

检查Notifications组件的代码,如果内部也注册了FCM消息监听器,只保留一处即可,删除多余的监听逻辑。

5. 清理缓存测试

测试前执行以下操作避免旧代码缓存影响:

  • 打开浏览器开发者工具 -> 应用 -> 存储 -> 清除站点数据
  • 进入服务工作线程面板,注销所有已注册的旧服务工作线程
  • 重新启动应用测试

额外注意事项

如果你使用带notification字段的推送 payload,FCM SDK默认会自动弹出系统通知,如果你需要自定义通知,要在onMessage回调中调用event.preventDefault()阻止默认行为,否则会出现默认通知和自定义通知同时弹出的情况。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:06:02