React项目集成FCM SDK 9后前后台均重复接收通知问题求解
问题原因
你遇到的重复通知问题是多个代码错误叠加导致的,核心问题如下:
App.js中FCM消息监听器重复注册:你没有把监听器放在useEffect中,每次组件重渲染都会新增一个监听器,收到消息时所有注册的回调都会触发,弹出多个通知onMessageListener的实现逻辑错误:你将持续触发的onMessage事件包装成了仅能resolve一次的Promise,不但会导致后续消息无法正常接收,还会随着组件渲染生成大量无用的监听器- Service Worker代码存在API调用错误:
showNotification第一个参数是通知标题,你直接传入了配置对象,调用失败后FCM SDK会触发兜底的默认通知,和你期望的自定义通知叠加 - Service Worker未完成Firebase初始化:你在sw代码中仅引入了
initializeApp但没有调用,会导致FCM SDK逻辑异常 - 额外监听器重复注册:你引入的
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
相关产品推荐
相关产品推荐

