【问题标题】:Firebase data not defined when used inside react useState在 react useState 中使用时未定义 Firebase 数据
【发布时间】:2021-04-04 17:35:46
【问题描述】:

我的问题很简单。我有一个 firebase 实时数据库,我正在从数据库中获取数据并尝试插入到 useState 中,这样我就可以在我的应用程序中显示这些数据。但无论我做什么,数据总是未定义或为空。奇怪的是,如果我在 jsx 组件中插入相同的确切数据或控制台记录它,它会毫无问题地显示。

这是我正在做的事情以及问题的描述:

首先是我的实时用户数据库

我只想访问 fullname 属性并将其插入到我的“名称”状态中

App.js

const userid = firebase.auth().currentUser.uid
const [usersList , setUsersList ] = useState([])
const [name, setName] = useState(usersList.fullname) //undefined

useEffect(() => {
const usersRef = firebase.database().ref('Users')
let query = usersRef.orderByChild('uid').equalTo(userid); 
query.on('value', (snapshot) => {
  const users = snapshot.val() 
  const usersList = []
  for (let id in users) {
    usersList.push({id, ...users[id]}) 
  }  
  setUsersList(usersList[0]) 
})
},[])

显示数据:

console.log(usersList.fullname) //displays my name perfectly well

return (
<div>{usersList.fullname}</div>
)

显示效果也很好

但是

const [name, setName] = useState(usersList.fullname) //undefined

这对我来说似乎完全不合逻辑! 如果您对为什么会发生这种情况有任何见解,请与我分享。

【问题讨论】:

  • 当你把你需要的东西放在第一个状态挂钩时,你为什么要第二次调用useState?你不想继续使用usersList吗?我也不清楚为什么要将单个对象值设置为称为“列表”的东西。 usersList 最初只包含一个列表。之后,它只包含一个对象值。
  • 它与这个问题无关。我们可以稍后讨论反应最佳实践,但根据我的逻辑 - 一切都按预期工作,除了在 useState 中显示它。你不同意吗?
  • 在一般意义上,代码是人类与其他人交流计算机应该做什么的一种方式。当这种通信中断并且变得难以辨别意图时,实际讨论计算机实际应该做什么也变得困难。

标签: reactjs firebase firebase-realtime-database react-hooks


【解决方案1】:

传递给useState的初始值只在功能组件第一次渲染时使用,但此时usersList是一个空数组,所以[].fullname是未定义的。之后你必须使用setName 来改变useState 的值,所以你可以调用:

setUsersList(usersList[0]) 
setName(usersList[0].fullname)

【讨论】:

    【解决方案2】:

    您看到的是预期的行为。从 Firebase 加载数据(就像调用大多数云 API)是一个异步操作。这就是您将函数(snapshot) =&gt; {...} 传递给操作的原因,以便在操作完成时它可以回调您。

    在此之前,该函数内的任何代码都没有运行,因此usersList 将具有其默认值。而且由于您将状态初始化为useState([]),其默认值为[],它没有fullname 成员。

    我猜你也想在设置usersList 之后设置用户名。所以:

    setUsersList(usersList[0]);
    setName(usersList[0].fullname);
    

    不相关:将用户存储在其 UID 下更为惯用。 ,而不是像现在这样使用push()。通过使用 UID 作为密钥,您可以:

    1. 自动确保每个 UID 只能存在一次,因为根据定义,键在节点中是唯一的。
    2. 无需查询即可加载具有给定 UID 的用户,如果您接触到数十万用户,则可以更好地扩展。
    3. 不再需要在回调中循环。

    所以在这种情况下,加载用户/名称变为:

    useEffect(() => {
      const usersRef = firebase.database().ref('Users')
      let query = usersRef.child(userid); 
      query.on('value', (snapshot) => {
        const user = snapshot.val() 
        setUsersList(user);
        setName(user.fullname);
      })
    },[])
    

    【讨论】:

    • 那么您如何解释在 jsx 组件中工作的全名变量?如果它不能在 jsx 或控制台日志中工作,你所说的对我来说才有意义。
    • 当您修改状态时(如setUsersList 所做的那样),它会导致 JSX 被重新渲染。但它不会导致const [name, setName] = useState(usersList.fullname) //undefined 重新运行。这就是 JSX 显示更新的原因,但 name 仍然是 undefined
    • 嗯,我复制了您的代码并将其替换为我的,但我收到错误,即用户的全名值未定义,但如果我只是编辑我的原始代码并添加 setName(usersList[0].全名)它的工作原理。有什么想法吗?
    • 并非如此。在这种情况下,我很难说出您的尝试与我的答案中的代码之间有什么区别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 2022-09-29
    • 1970-01-01
    相关资源
    最近更新 更多