我正在使用 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: {...}
答案 0 :(得分:0)
由于这 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 依赖项。