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

如何用React Hooks结合Firestore实现表格仅展示更新数据

实现Firestore数据更新时React表格自动同步最新数据

问题背景

已经实现从Firestore获取数据并展示在React表格中,现在需要实现当Firestore数据发生增删改时,网页表格自动更新展示最新数据,无需手动点击刷新按钮。

解决方案

核心思路是利用Firestore的onSnapshot方法实现集合的实时监听,当数据变化时自动更新React组件状态,从而让表格同步刷新。以下是基于现有代码的修改方案:

1. 先修改BookDataService,添加实时监听方法

在book.services.js中新增订阅数据变化的方法:

// book.services.js
import { db } from '../firebase-config'; // 引入你的Firebase配置
import { collection, onSnapshot, getDocs } from 'firebase/firestore';

class BookDataService {
  // 保留原有一次性获取数据的方法(用于手动刷新)
  getAllBooks = async () => {
    const colRef = collection(db, 'books');
    const snapshot = await getDocs(colRef);
    return snapshot;
  };

  // 新增:实时监听集合数据变化的方法
  subscribeToBooks = (callback) => {
    const colRef = collection(db, 'books');
    // 返回取消订阅的函数,用于组件卸载时清理
    return onSnapshot(colRef, (snapshot) => {
      const booksData = snapshot.docs.map(doc => ({ ...doc.data(), id: doc.id }));
      callback(booksData);
    });
  };
}

export default new BookDataService();

2. 修改React表格组件,实现实时更新

import React, { useEffect, useState } from "react";
import { Button } from "react-bootstrap";
import Table from 'react-bootstrap/Table';
import BookDataService from "../../services/book.services";
import "./table.css";

const TableList = () => {
  // 统一变量命名,提升可读性
  const [books, setBooks] = useState([]);

  useEffect(() => {
    // 订阅Firestore数据变化,获取取消订阅函数
    const unsubscribe = BookDataService.subscribeToBooks((updatedBooks) => {
      setBooks(updatedBooks);
    });

    // 组件卸载时取消订阅,防止内存泄漏
    return () => unsubscribe();
  }, []);

  // 保留手动刷新功能
  const handleRefresh = async () => {
    const data = await BookDataService.getAllBooks();
    setBooks(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
  };

  return (
    <>
      <div className="mb-4">
        <Button variant="success edit" onClick={handleRefresh}>
          Refresh
        </Button>
      </div>

      <Table striped bordered hover variant="dark" size="md">
        <thead>
          <tr>
            <th>RollNo</th>
            <th>Name</th>
            <th>Student ID</th>
            <th>Subject</th>
            <th>Room</th>
            <th>Date</th>
            <th>Time</th>
          </tr>
        </thead>
        <tbody>
          {books.map((doc, index) => {
            const firebasetime = new Date(
              doc.timeStamp.seconds * 1000 + doc.timeStamp.nanoseconds / 1000000,
            );
            const date = firebasetime.toDateString();
            const timeStamp = firebasetime.toLocaleTimeString();
            
            return (
              <tr key={doc.id}>
                <td>{index + 1}</td>
                <td>{doc.name}</td>
                <td>{doc.sid}</td>
                <td>{doc.Subject}</td>
                <td>{doc.Room}</td>
                <td>{date}</td>
                <td>{timeStamp}</td>
              </tr>
            );
          })}
        </tbody>
      </Table>
    </>
  );
};

export default TableList;

关键改动说明

  • 实时监听替代一次性获取:用onSnapshot替代getDocs,该方法会在集合数据发生任何变化(新增、修改、删除文档)时自动触发回调,将最新数据同步到组件状态。
  • 清理订阅:在useEffect中返回取消订阅的函数,确保组件卸载时停止监听,避免内存泄漏。
  • 统一变量命名:将原profile改为books,和setBooks保持一致,提升代码可读性。
  • 保留手动刷新:保留原有刷新按钮,方便需要时手动触发数据同步。

内容的提问来源于stack exchange,提问作者TruReS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:05:44