You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中使用Firebase V9检测用户在线/离线状态

Firebase V9 用户在线/离线状态显示异常:snap.val() 始终返回 false

问题描述

我开发了一款聊天应用,需要在Firebase V9中实现用户在线、离线状态显示,覆盖窗口/标签页关闭、断开连接、登出等场景。已配置好firebase.js,但编写代码时遇到问题:即使指定UID的用户处于在线状态,监听.info/connected返回的snap.val()始终为false。

配置代码(firebase.js)

import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getStorage } from 'firebase/storage';
import { getFirestore } from 'firebase/firestore';
import { getDatabase } from 'firebase/database';

const firebaseConfig = {
  apiKey: apikey,
  authDomain: 'xxxxx.firebaseapp.com',
  projectId: 'xxxx',
  storageBucket: 'xxxx.appspot.com',
  messagingSenderId: 'xxxxxx',
  appId: '1:xxxxxxxx:web:xxxxxxx',
};

export const app = initializeApp(firebaseConfig);
export const auth = getAuth();
export const storage = getStorage();
export const db = getFirestore();
export const firebaseDb = getDatabase(app);

尝试的代码

useEffect(() => {
      const connectedRef = ref(firebaseDb, '.info/connected');
      const uid = '3bEw4VqpMieSzR8NBfDz6XqG33l1';
      const myConnectionsRef = ref(firebaseDb, 'users', uid);
      console.log(myConnectionsRef, 'myConnectionsRef');
      onValue(connectedRef, (snap) => {
        console.log(snap.val(), 'snap');
        if (snap.val() === true) {
          console.log('TRUE');
          if (user) {
            set(myConnectionsRef, 'connected');
            updateFirestoreUser(user, true);
          }
        } else {
          console.log('FALSE');
          updateFirestoreUser(user, false);
        }
        //onDisconnect(myConnectionsRef)
        //.set("disconnected")
        //.then(() => {
        //   updateFirestoreUser(user, false);
        //});
      });
    }, []);

补充:更新后问题依旧,即使指定UID用户在线,snap.val()仍显示false。


问题排查与解决方案

1. 实时数据库引用路径错误

你创建myConnectionsRef的写法有误,ref函数的路径参数需要正确拼接:

// 错误写法
const myConnectionsRef = ref(firebaseDb, 'users', uid);
// 正确写法1:拼接路径字符串
const myConnectionsRef = ref(firebaseDb, `users/${uid}`);
// 正确写法2:使用child方法
const myConnectionsRef = ref(firebaseDb, 'users').child(uid);

原写法会导致引用路径异常,进而影响状态监听逻辑。

2. 检查实时数据库规则

确保数据库规则允许读取.info/connected节点,默认规则支持,但自定义规则时需保留权限:

{
  "rules": {
    ".info": {
      ".read": true
    },
    // 其他自定义规则...
  }
}

3. 完善离线状态处理(恢复onDisconnect)

onDisconnect是实现离线状态自动更新的核心,需修正并恢复:

useEffect(() => {
  if (!user) return; // 先判断用户是否存在,避免空值错误

  const connectedRef = ref(firebaseDb, '.info/connected');
  const userStatusRef = ref(firebaseDb, `users/${user.uid}/status`); // 用独立字段存储状态更清晰

  // 取消监听的函数,组件卸载时执行
  const unsubscribe = onValue(connectedRef, (snap) => {
    if (snap.val() === true) {
      // 在线时设置状态,并绑定离线触发逻辑
      set(userStatusRef, 'online')
        .then(() => {
          onDisconnect(userStatusRef).set('offline');
          updateFirestoreUser(user, true);
        });
    } else {
      updateFirestoreUser(user, false);
    }
  });

  return () => unsubscribe();
}, [user]); // 依赖项添加user,确保用户状态变化时重新执行监听

4. 修复useEffect依赖项缺失

原代码依赖项为空数组,user状态变化时不会重新执行监听逻辑,需将user加入依赖数组。

5. 验证网络与数据库连接

检查客户端网络状态,确认能正常访问Firebase实时数据库;同时验证数据库中users节点的结构是否符合预期。


内容的提问来源于stack exchange,提问作者Srivathsa k m

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 06:26:27