如何向多设备发送Expo推送通知?Firestore取token单设备接收问题
Expo推送通知仅能推送给单台设备的问题修复
问题根源
- React setState异步特性导致取值错误:调用
setRead后立即读取read变量,此时read尚未完成更新,导致readx拿到的是旧数据而非完整的令牌数组。 - 错误格式化令牌数组:Expo推送API的
to字段支持单个令牌字符串或令牌数组,你用JSON.stringify将数组转为字符串后,API无法识别为多设备列表,仅会处理字符串中的第一个有效令牌。
修复代码
修正推送函数
async function sendPushNotification(tokens) { const message = { to: tokens, // 直接传入令牌数组,无需JSON转换 sound: "default", title: "Original Title", body: "And here is the body!", data: { someData: "goes here" }, }; // 调用Expo推送API发送消息(补充你可能遗漏的发送逻辑) await fetch('https://exp.host/--/api/v2/push/send', { method: 'POST', headers: { Accept: 'application/json', 'Accept-encoding': 'gzip, deflate', 'Content-Type': 'application/json', }, body: JSON.stringify(message), }); }
修正令牌获取函数
方案一:直接在获取令牌后调用推送,避开setState异步问题
const retrieveNetwork = async () => { try { const q = query(collection(db, "users")); const querySnapshot = await getDocs(q); const tokens = querySnapshot.docs.map((doc) => doc.data().expoUser); setRead(tokens); // 直接推送,无需依赖state更新 await sendPushNotification(tokens); } catch (e) { alert(e); } };
方案二:用useEffect监听state变化,确保令牌更新后再推送
const retrieveNetwork = async () => { try { const q = query(collection(db, "users")); const querySnapshot = await getDocs(q); const tokens = querySnapshot.docs.map((doc) => doc.data().expoUser); setRead(tokens); } catch (e) { alert(e); } }; // 监听read状态变化,更新后触发推送 useEffect(() => { if (read.length > 0) { sendPushNotification(read); } }, [read]);
内容的提问来源于stack exchange,提问作者Andres Pelaez
相关产品推荐
相关产品推荐

