使用NetInfo检测用户在线/离线状态异常问题排查
问题诊断与修复方案
核心问题分析
初始在线状态判断逻辑错误
代码中初始设置用户在线状态时,用socket.id === user.socketId判断,这只会把当前客户端自己标记为在线,其他用户的isOnline永远为false,完全不符合需求。NetInfo逻辑破坏用户在线状态
网络状态监听中调用updateAllIsOnline,会把所有用户的在线状态统一设置为当前设备的网络连接状态,混淆了设备网络状态和用户在线状态,属于严重逻辑错误。缺少socket身份注册
客户端连接socket后,未向服务器发送用户身份信息,导致服务器无法识别当前用户,也无法推送正确的在线用户列表。初始用户列表获取时机问题
获取用户列表时socket可能还未完全建立连接,导致依赖socket.connected的判断失效。
修复后的完整代码
import { View, Text, FlatList, StyleSheet, StatusBar, TouchableOpacity } from 'react-native'; import React, { useState, useEffect } from 'react'; import axios from 'axios'; import io from 'socket.io-client'; const SOCKET_URL = 'http://10.100.102.23:3002'; export default function MentorsChat() { const [selectedId, setSelectedId] = useState(null); const [users, setUsers] = useState([]); const [socket, setSocket] = useState(null); useEffect(() => { // 创建socket连接 const socketInstance = io(SOCKET_URL); setSocket(socketInstance); // 连接成功后,向服务器发送用户身份(替换为当前登录用户真实ID) socketInstance.on('connect', () => { const currentUserId = '当前登录用户ID'; socketInstance.emit('register', currentUserId); // 连接稳定后获取用户列表 axios.get('http://10.100.102.23:3002/api/users') .then(response => { setUsers(response.data); }) .catch(error => { console.log(error); }); // 监听服务器推送的在线用户列表 socketInstance.on('onlineUsers', (onlineUserIds) => { setUsers(prevUsers => prevUsers.map(user => ({ ...user, isOnline: onlineUserIds.includes(user._id) }))); }); }); // 监听单个用户上线事件 socketInstance.on('online', userId => { setUsers(prevState => prevState.map(user => user._id === userId ? { ...user, isOnline: true } : user )); }); // 监听单个用户下线事件 socketInstance.on('offline', userId => { setUsers(prevState => prevState.map(user => user._id === userId ? { ...user, isOnline: false } : user )); }); // 组件卸载时关闭连接 return () => { socketInstance.close(); }; }, []); const renderItem = ({ item }) => { const backgroundColor = item._id === selectedId ? "#6e3b6e" : "#f9c2ff"; return ( <TouchableOpacity onPress={() => setSelectedId(item._id)} style={[styles.item, { backgroundColor }]}> <Text style={styles.title}>{item.fullName}</Text> <Text style={styles.subtitle}>{item.isMentor ? "Mentor" : "Not a mentor"}</Text> <Text style={styles.subtitle}>{item.isOnline ? "Online" : "Offline"}</Text> </TouchableOpacity> ); }; return ( <View style={styles.container}> <FlatList data={users} renderItem={renderItem} keyExtractor={(item) => item._id} extraData={selectedId} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, marginTop: StatusBar.currentHeight || 0, }, item: { backgroundColor: '#f9c2ff', padding: 20, marginVertical: 8, marginHorizontal: 16, }, title: { fontSize: 32, }, subtitle: { fontSize: 16, marginTop: 4, color: '#666', }, });
服务器端配套要求
- 维护在线用户ID列表,通过
register事件记录用户ID与socket的映射关系。 - 客户端连接后,主动推送当前所有在线用户ID列表(触发
onlineUsers事件)。 - 用户断开连接时,向其他客户端广播
offline事件。
内容的提问来源于stack exchange,提问作者armory victory
相关产品推荐
相关产品推荐

