如何用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
相关产品推荐
相关产品推荐

