如何创建可通过按钮点击筛选的Firestore数据表格?
解决Firestore数据筛选表格的无限循环问题
问题根源
你的代码陷入无限循环的核心原因是按钮的onClick属性错误地直接调用了函数:
<button onClick={handleUpcoming()}>Upcoming</button> <button onClick={handlePast()}>Past</button>
这种写法会导致组件每次渲染时立即执行handleUpcoming和handlePast,调用setAccounts更新状态后触发组件重渲染,进而再次执行这两个函数,形成无限循环。
另外还有两个可优化点:
currentDate在组件每次渲染时都会重新计算,建议用useMemo缓存- 列表渲染的
<tr>缺少key属性,会触发React性能警告
修改后的完整代码
import React, { useState, useMemo, useEffect } from 'react'; import './App.css'; import db from './firebase'; import 'react-toastify/dist/ReactToastify.css'; const App = () => { // 用useMemo缓存当前日期,避免每次渲染重复计算 const currentDate = useMemo(() => new Date().toISOString().slice(0, 10), []); const [accounts, setAccounts] = useState([]); // 获取即将到来的预约 const handleUpcoming = async () => { const response = db.collection('accounts').where('schedule', '>', currentDate); const data = await response.get(); const newAccounts = data.docs.map(item => ({...item.data(), id: item.id})) // 添加id作为key setAccounts(newAccounts); } // 获取已过去的预约 const handlePast = async () => { const response = db.collection('accounts').where('schedule', '<', currentDate); const data = await response.get(); const newAccounts = data.docs.map(item => ({...item.data(), id: item.id})) // 添加id作为key setAccounts(newAccounts); } // 组件挂载时默认加载所有预约(可选,根据需求调整) useEffect(() => { const fetchAllAccounts = async () => { const response = db.collection('accounts'); const data = await response.get(); const newAccounts = data.docs.map(item => ({...item.data(), id: item.id})) setAccounts(newAccounts); }; fetchAllAccounts(); }, []); return ( <div className="app-container"> <h1>Appointments</h1> <div className="button-container"> {/* 传递函数引用,而非立即执行 */} <button onClick={handleUpcoming}>Upcoming</button> <button onClick={handlePast}>Past</button> <div className="scrollbar"> <table> <thead> {/* 可选:添加表头 */} <tr> <th>Name & Email</th> <th>Schedule</th> <th>Service</th> <th>Mobile Number</th> </tr> </thead> <tbody> {accounts.map(account => ( // 添加唯一key属性 <tr key={account.id}> <td className="appointmentDataOne"> {account.name} <div className="appointmentDataTwo">{account.email}</div> </td> <td className="appointmentDataOne">{account.schedule}</td> <td className="appointmentDataTwo">{account.service}</td> <td className="appointmentDataTwo">{account.mobileNumber}</td> </tr> ))} </tbody> </table> </div> </div> </div> ); } export default App;
关键修改说明
- 修复无限循环:将按钮的
onClick={handleUpcoming()}改为onClick={handleUpcoming},传递函数引用而非立即执行,只有点击按钮时才会触发函数。 - 缓存当前日期:用
useMemo缓存currentDate,确保组件重新渲染时不会重复生成日期字符串。 - 添加列表key:在映射
accounts时,将Firestore文档的id添加到数据中,作为<tr>的key属性,符合React列表渲染规范,避免性能警告。 - 初始数据加载(可选):通过
useEffect在组件挂载时默认加载所有预约数据,提升用户体验。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

