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

React useEffect获取Firestore数据首屏加载不显示问题

问题原因

你的代码存在三个直接导致首屏无法正常渲染的问题:

  • 违反React state不可变原则:你直接对state状态dataArray执行push操作,这种修改不会被React追踪到,不会触发组件重渲染。代码热更新时开发服务器会强制组件重渲染,所以你改完代码能看到数据,正常首屏加载流程下不会触发这个强制刷新,自然看不到内容。
  • 异步逻辑执行顺序错误:
    • 你写的.then(fetchClassData())是立即执行fetchClassData,不是等fetchUserData执行完成后再调用,等于两个请求几乎同时触发
    • React的setState是异步执行的,你在fetchUserData里刚调用setClassesArray,立刻在fetchClassData里读classesArray,拿到的还是初始值空数组,根本读不到刚拉取到的课程ID列表
  • 代码笔误:组件里写了kclassName属性,正确的属性名是className,同时漏了从react引入useState、useEffect两个Hook,运行时会直接抛错。
修复后代码

直接把两个数据拉取逻辑放到同一个异步流程里,不要通过state传递中间的课程ID列表,拉取完所有课程数据后,一次性调用setDataArray触发组件渲染:

import '../css/ClassBox.css'
import { useState, useEffect } from 'react'
import { db } from '../Firebase/firebase'
import { doc, getDoc } from 'firebase/firestore';

function ClassBox() {

  const [dataArray, setDataArray] = useState([])

  useEffect(() => {
    const fetchAllData = async () => {
      // 拉取用户数据
      const userId = localStorage.getItem('id')
      const userData = await getDoc(doc(db, 'users', userId))
      // 处理课程ID列表,不用存到state里,直接用局部变量承接
      const classIdList = userData.data().classes
        .toString()
        .replace(/\s*\,\s*/g, ",")
        .trim()
        .split(",")
      
      // 串行拉取所有课程数据
      const classDataList = []
      for(let i=0; i<classIdList.length; i++) {
        const classRes = await getDoc(doc(db, 'classes', classIdList[i]))
        classDataList.push(classRes.data())
      }
      // 一次性更新state,触发重渲染
      setDataArray(classDataList)
    }

    fetchAllData()
  }, [])

  return (
    <div className='classBoxList'>
        {dataArray.map((classes) => (
            <div className='classBox' key={classes.classCRN}>
                <div className='classBoxContainer'>
                    <div className='classBoxWrapper'>
                        <div className='statusContainer'>
                            <h3>CS 106</h3>
                            <h4>{classes.status}</h4>
                        </div>
                        <div className='classInfoContainer'>
                            <ul>
                                <li>CS 106 - {classes.classCRN}</li>
                                <li>{classes.instructorName}</li>
                                <li>{classes.building}</li>
                                <li>{classes.instructionMethod}</li>
                                <li>Seats: {classes.takenSeats}/{classes.totalSeats}</li>
                                <li>Remaining: {classes.remainingSeats}</li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        ))}
    </div>
  )
}

export default ClassBox
额外优化点
  • 给map遍历的最外层div加了key={classes.classCRN},避免React控制台报列表key的警告
  • 去掉了li标签上多余的key属性,key只需要加在遍历的最外层元素上
  • 去掉了多余的classesArray状态,中间值不需要存到state里,减少不必要的重渲染

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:18:14