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

React.js中调用readContacts()无法在网页输出内容是什么原因?

问题原因

  • 你的readContacts函数本身没有返回值:回调函数内的return snapshot.val()仅将值返回给Firebase的on事件回调方法,而非readContacts的调用方,直接调用readContacts()拿到的是undefined,自然无法渲染。
  • Firebase数据库读取是异步操作,就算你做了返回值处理,也无法在同步渲染逻辑里直接拿到异步返回的结果。
  • 你没有把联系人数据存入React响应式状态,就算拿到了数据也无法触发组件重新渲染更新页面。

修正方案

1. 修改ContactsContext.js

import React, { useContext, useState } from "react"
import { db } from "../firebase"

import { useAuth } from "./AuthContext"

const ContactsContext = React.createContext()

export function useContacts() {
  return useContext(ContactsContext)
}

export function ContactsProvider({ children }) {
  const { currentUser } = useAuth()
  // 新增响应式状态存储联系人数据
  const [contacts, setContacts] = useState([])

  function createContact(email, firstName, lastName) {
    db.ref("users/" + currentUser.uid + "/contacts/" + firstName + " " + lastName).set({
      Email: email,
      FirstName: firstName,
      LastName: lastName
    })
  }

  function readContacts() {
    // 存储监听器引用,后续可以解绑避免内存泄漏
    const contactRef = db.ref("users/" + currentUser.uid + "/contacts/")
    contactRef.on("value", (snapshot) => {
      const data = snapshot.val()
      // 将Firebase返回的对象转为数组方便渲染
      const contactList = data ? Object.values(data) : []
      setContacts(contactList)
    })
    // 返回解绑函数
    return () => contactRef.off("value")
  }

  const value = {
    createContact,
    readContacts,
    // 把联系人状态加入context
    contacts
  }

  return (
    <ContactsContext.Provider value={value}>
      {children}
    </ContactsContext.Provider>
  )
}

2. 修改Contacts.js

import React, { useEffect } from "react"
import { ListGroup } from "react-bootstrap"

import { useContacts } from "../contexts/ContactsContext"
  
export default function Contacts() {
  const { readContacts, contacts } = useContacts()

  // 组件挂载时初始化数据监听,卸载时解绑监听器
  useEffect(() => {
    const unSubscribe = readContacts()
    return () => unSubscribe()
  }, [readContacts])

  return (
    <ListGroup variant="flush">
      {/* 遍历渲染联系人列表 */}
      {contacts.map((contact, index) => (
        <ListGroup.Item key={index}>
          {contact.FirstName} {contact.LastName} - {contact.Email}
        </ListGroup.Item>
      ))}
    </ListGroup>
  )
}

补充说明

  • 当前你用firstName + lastName作为数据库节点key存在重名覆盖的风险,建议改用Firebase的push()方法生成唯一ID作为key,或者用邮箱地址这类唯一标识。
  • 如果你不需要实时监听联系人数据更新,可以把on("value")改为once("value"),读取一次后就自动结束请求,不需要手动解绑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 00:36:04