如何解决FCM - messages().onMessage 重复回调 - 不使用 useEffect
我正在使用 FCM 将消息发送到 Android 应用程序,然后该应用程序将消息呈现到 FlatList 组件中。当我收到新的 FCM 消息时,我想刷新 FlatList 组件,以便在列表中显示最新的消息。我正在使用 useEffect 通过 setRefreshPage() 触发刷新。
下面的代码效果很好,除了每次收到 FCM 消息并且 useEffect 触发时,它似乎创建了第二个前台侦听器,从而导致后续消息的重复通知。我不认为 unsubscribeOnMessage();正在删除 useEffect 中现有的前台侦听器。
每次回调都会加倍,即第一条消息收到 1 个 FCM 消息回调,下一条消息有 2 条回调,下一条消息有 4 条回调,等等。这让我觉得正在使用额外的消息 ().onMessage 前台侦听器在每个 useEffect 触发器上创建。
当 useEffect 被触发时删除消息监听器的正确方法是什么?
到目前为止,我只在 Android 上测试过这段代码。
function HomeScreen() {
const [data,setData] = useState([]);
const [refreshPage,setRefreshPage] = useState(false);
useEffect(async () => {
const value = await AsyncStorage.getItem('storedMessages');
// ...functions to retrieve and sort historical messages into array "sortedInput"
setData(sortedInput); // setState to provide initial data for FlatList component
};
const unsubscribeOnMessage = messaging().onMessage(async remoteMessage => {
console.log("DEBUG: Received FCM message: " + JSON.stringify(remoteMessage));
// Function to process new message and insert into local storage
await _handleNewMessage(remoteMessage);
// Display notification to user
await onDisplayNotification(remoteMessage);
// Trigger refresh of FlatList component with setState
setRefreshPage(Math.random() * 100);
});
return () => {
unsubscribeOnMessage();
};
},[refreshPage]);
// Render messages into FlatList view
function renderMessagesFlatList(data) {
if (isLoading) {
return (
<ActivityIndicator
size="large"
color="#0000ff"
/>
);
} else if (data.length === 0) {
return (
<Text>No notifications to display</Text>
);
} else {
return (
<FlatList
data={data}
keyExtractor={(item,index) => item.id}
renderItem={({ item }) => (
<>
<View style={{ flexDirection: 'row',flex: 1 }}>
<Image
style={{ width: 40,height: 40 }}
source={{uri:item.icon}}
/>
<View style={{ flex: 1,paddingLeft: 5 }}>
<Text style={{ color: '#000000',fontWeight: 'bold' }}>{item.sender}</Text>
<Text>{timeSince(item.time)}</Text>
</View>
</View>
<Text style={{ paddingTop: 4 }}>{item.body}</Text>
<Divider style={{ backgroundColor: '#e7e5e5',height: 2,marginTop: 5,marginBottom: 5 }} />
</>
)}
/>
);
}
};
return (
<View style={{ margin: 5 }} >
{console.log("DEBUG: isLoading = " + isLoading)}
{console.log("DEBUG: data = " + JSON.stringify(data))}
{renderMessagesFlatList(data)}
</View>
);
};
这是我每分钟发送一条 FCM 消息时最终在日志文件中看到的内容:
04-22 08:40:00.000 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:41:00.000 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:41:00.006 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:42:00.000 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:42:00.004 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:42:00.009 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:42:00.014 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.000 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.006 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.011 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.017 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.021 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.028 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.036 ReactNativeJS: DEBUG: Received FCM message: {...}
04-22 08:43:00.049 ReactNativeJS: DEBUG: Received FCM message: {...}
解决方法
由于这 2 行,您会收到 FCM 重复更新,从而导致循环,这是一种反模式。
setRefreshPage(Math.random() * 100); //<-- You are updating the state refreshPage
},[refreshPage]); // <--- You use refreshPage as a dependency means useEffect will be called. And then you will setRefreshPage again
除此之外,我无法给您提供更多建议,因为我不确定您为什么设置了 setRefreshPage。如果您希望它在页面加载时仅触发一次,则删除 refreshPage 依赖项。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。