You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React应用无法从Firebase获取并渲染分类数据,class为items的Div未显示问题排查

问题分析与修复方案

我帮你梳理下代码里的几个关键问题,这些就是导致你的.items容器没渲染的原因:

  • 条件渲染逻辑搞反了:你现在写的是loader === true && ...,意思是加载中才渲染内容,但这时候数据还没拿到啊!应该反过来,当loader === false(加载完成)的时候才渲染数据,加载中可以显示个加载提示,比如“加载中...”。
  • 错误地包裹了data数组:你用[data].map(...),这相当于把原本的数组又包了一层新数组,map遍历的是这个新数组的每一项(也就是原data数组本身),这完全没必要,直接用data.map(...)就行。
  • map函数没有返回元素:你在map里用了大括号{},但没有显式return JSX元素,JS里如果函数用大括号包裹,必须写return才能返回值,不然默认返回undefined,自然不会渲染任何东西。你可以要么加return,要么把大括号改成小括号(隐式返回)。
  • 异步操作的时机错误onSnapshot是异步的,你现在在回调外面就执行setdata(items)setloader(false),这时候回调还没执行,items还是空数组,所以data一直是空的,自然没内容渲染。得把这两个状态更新放在onSnapshot的回调里面,确保拿到数据后再更新状态。
  • 没有正确获取文档ID:你用doc.data()只能拿到文档里的字段,但dev.id是undefined,因为你没把doc的id存到items里,所以push的时候要把id也带上,比如items.push({...doc.data(), id: doc.id})

修正后的代码

import { useEffect, useState } from "react";
import firebase from "../../Firebase.config";
import './CategoriesPage.css'

const CategoriesPage = () => {
  const ref = firebase.firestore().collection("Categories")
  const [data, setData] = useState([]) // 变量名改用驼峰式,更符合React规范
  const [loader, setLoader] = useState(true)

  function getData() {
    ref.onSnapshot((querySnapshot) => {
      const items = []
      querySnapshot.forEach((doc) => {
        // 把文档ID存入对象,确保map时能拿到唯一的key值
        items.push({...doc.data(), id: doc.id})
      })
      // 拿到数据后再更新状态,放在回调内部保证异步顺序
      setData(items)
      setLoader(false)
    })
  }

  useEffect(() => {
    getData()
  }, [])

  return (
    <section className="Categoriebox">
      {/* 加载中显示提示,加载完成后渲染数据 */}
      {loader ? (
        <p>加载中...</p>
      ) : (
        data.map((dev) => (
          <div className="items" key={dev.id}>
            <h1>{dev.name}</h1>
          </div>
        ))
      )}
    </section>
  )
};

export default CategoriesPage;

额外优化建议

如果你的场景只需要一次性获取数据,不需要实时监听集合变化,可以改用get()方法,避免不必要的实时监听:

// 改用get()的异步版本
async function getData() {
  try {
    const querySnapshot = await ref.get()
    const items = []
    querySnapshot.forEach((doc) => {
      items.push({...doc.data(), id: doc.id})
    })
    setData(items)
  } catch (err) {
    console.error("获取数据失败:", err)
  } finally {
    setLoader(false)
  }
}

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

火山引擎 最新活动