useEffect获取数据无法填充DataGrid的问题排查
解决getLogs返回数组无法填充DataGrid的问题
问题根源
- 异步处理失效:
getLogs中使用forEach(async (log) => {})时,forEach不会等待内部的异步getDoc请求完成,循环执行完毕后直接返回空数组rows,导致拿到的数据不完整。 - 命名冲突:useEffect内部定义的函数名与状态变量名都是
logs,造成作用域混乱,影响状态更新逻辑。
修复后的代码
function.js
export async function getLogs() { const q = query(collection(db, "logs"), orderBy("date", "desc")); const docQuery = await getDocs(q); // 用map+Promise.all等待所有异步请求完成后再返回结果 const rows = await Promise.all(docQuery.docs.map(async (log, index) => { const useref = await getDoc(log.data().user); const date = new Timestamp( log.data().date.seconds, log.data().date.nanoseconds ) .toDate() .toLocaleString("en-sg"); return { id: index + 1, name: useref.data().name, activity: log.data().activity, date: date, }; })); return rows; }
LogDetails.jsx
const columns = [ { field: "id", headerName: "ID", width: 30 }, { field: "name", headerName: "Name", width: 250, }, { field: "activity", headerName: "Activity", width: 350, }, { field: "date", headerName: "Date", width: 250, }, ]; export default function LogDetails() { const [logs, setLogs] = useState([]); useEffect(() => { // 重命名函数避免与状态变量冲突 const fetchLogs = async () => { const res = await getLogs(); setLogs(res); }; fetchLogs(); // 可选:添加清理逻辑,防止组件卸载后执行无效状态更新 return () => { // 若需取消Firebase请求,可在此处调用unsubscribe方法 }; }, []); return ( <Box sx={{ width: "100%" }}> {logs.length ? ( <DataGrid rows={logs} columns={columns} pageSize={10} rowsPerPageOptions={[10]} disableSelectionOnClick autoHeight /> ) : ( <div>加载中...</div> )} </Box> ); }
修复说明
- 异步逻辑修正:通过
map生成异步请求数组,再用Promise.all等待所有请求完成,确保返回的rows是填充完整的数据数组。 - 命名冲突解决:将useEffect内的函数名改为
fetchLogs,避免与状态变量logs重名,消除作用域歧义。 - 体验优化:替换
.then()为async/await提升代码可读性,添加加载提示改善用户等待体验,用index+1替代手动维护count变量,简化逻辑。
内容的提问来源于stack exchange,提问作者Kristin Chia
相关产品推荐
相关产品推荐

