React.js加载Firestore文档网格首次点击导航不渲染问题
问题核心原因
你的代码存在致命的异步逻辑错误,导致首次加载时状态更新早于数据拉取完成,之前加加载态无效是因为加载态的判断逻辑从一开始就拿不到正确的加载完成时机:
getGrid函数中,你只等待了getDocs的请求完成,但遍历文档时调用的getAuthor是独立的异步Promise,你没有等待这些Promise全部执行完成,就提前返回了空的gridData数组。后续getAuthor请求完成后往数组里push值的操作,发生在getGrid已经return之后,React根本感知不到数据变化,不会触发重渲染。useEffect的依赖数组为空,当groupBy参数变化时不会重新触发数据拉取;同时列表渲染时把整个对象当作key,会导致React diff计算异常,偶发渲染不更新的问题。
修复方案
1. 重写getGrid函数,等待所有异步请求完成后再返回数据
用Promise.all包裹所有文档项的处理逻辑,确保所有作者信息拉取完成、数组组装完毕后再返回结果,同时补全作者不存在的边界判断,避免空值报错:
const getGrid = async (type) => { const db = getFirestore(app); const gridSnapshot = await getDocs(collection(db, type)); // 等待所有作者请求完成,同步组装数据 const rawGridData = await Promise.all( gridSnapshot.docs.map(async (item) => { const itemData = item.data(); const author = await getAuthor(itemData.Author.id); // 作者信息不存在时返回null,后续过滤 if (!author) return null; return { id: item.id, title: itemData.title, link: `/materials/type=${type}/uuid=${item.id}`, thumbnail: "#", type: type, authors: [{ name: `${author.FirstName} ${author.LastName}`, imageUrl: author.profileUrl, profileUrl: `/user/id=${author.id}` }] }; }) ); // 过滤无效项 return rawGridData.filter(Boolean); }
2. 修复主组件的useEffect逻辑和列表渲染规则
补全useEffect依赖项,加入正确的加载态判断,同时用唯一ID作为列表key:
const Materials = ({ groupBy }) => { const [grid, setGrid] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); getGrid(groupBy) .then(gridn => { setGrid(gridn); }) .catch(err => { console.error("数据拉取失败:", err); }) .finally(() => { setLoading(false); }); }, [groupBy]); // 加入groupBy依赖,分类切换时自动重拉数据 if (loading) { return <div className="w-full text-center py-10">内容加载中...</div> } return ( <div className="w-full flex flex-col justify-content items-center m-auto"> <div className="materials w-11/12 lg:p-5 pt-5 grid 2xl:grid-cols-4 xl:grid-cols-3 lg:grid-cols-2 gap-4 gap-y-6"> {/* 用唯一id作为key,不要传入整个对象 */} {grid.map((i) => (<Material key={i.id} info={i} />))} </div> </div> ) }
额外优化建议
如果列表数据量较大,逐个调用getAuthor会产生多次Firestore读请求,可以考虑把作者ID去重后批量拉取作者文档,减少请求次数、提升加载速度。
内容的提问来源于stack exchange,提问作者Kaloyan Doychinov
相关产品推荐
相关产品推荐

