在React useState中使用时未定义Firebase数据 [英] Firebase data not defined when used inside react useState

查看:46
本文介绍了在React useState中使用时未定义Firebase数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题很简单.我有一个Firebase实时数据库,我正在从数据库中获取数据并尝试插入useState内,以便随后可以在我的应用程序中显示此数据.但是无论我做什么,数据始终是未定义的或为null.奇怪的是,如果我在jsx组件中插入相同的数据或通过控制台记录它,它的显示就没有任何问题.

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

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

我只是想访问fullname属性并将其插入到我的"name"状态内

App.js

  const userid = firebase.auth().currentUser.uidconst [usersList,setUsersList] = useState([])const [name,setName] = useState(usersList.fullname)//未定义useEffect(()=> {const usersRef = firebase.database().ref('Users')让查询= usersRef.orderByChild('uid').equalTo(userid);query.on('value',(snapshot)=> {const用户= snapshot.val()const usersList = []为(在用户中留下ID){usersList.push({id,... users [id]})}setUsersList(usersList [0])})},[]) 

显示数据:

  console.log(usersList.fullname)//完美显示我的名字 

还有

 返回(< div> {usersList.fullname}</div>) 

显示效果也很好

但是

  const [name,setName] = useState(usersList.fullname)//未定义 

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

解决方案

您看到的是预期的行为.从Firebase加载数据(就像调用大多数云API一样)是异步操作.这就是为什么要传递函数(snapshot)=>{...} 放入操作中,以便操作完成后可以回叫您.

在这种情况下,该函数中的所有代码均未运行,因此 usersList 将具有其默认值.而且由于将状态初始化为 useState([]),其默认值是 [] ,它没有 fullname 成员./p>

我最大的猜想是,设置 usersList 后,您也想设置用户名.所以:

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


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

  1. 自动确定每个UID只能存在一次,因为键在定义上在节点中是唯一的.
  2. 可以使用给定的UID加载用户而无需查询,如果您覆盖了成千上万的用户,则扩展性更好.
  3. 不再需要在回调中循环.

因此,在这种情况下,加载用户/名称将变为:

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

My issue is very simple. I have a firebase realtime database and i am fetching data from the database and trying to insert in inside a useState so that i can then display this data in my app. But no matter what i do, the data is always undefined or null. Strangely enough if i insert that same exact data inside a jsx component or console log it, it displays without any problem.

Here's what i am doing and a description of the problem:

First here is my realtime-database with users

I simply want to access the fullname property and insert that inside my 'name' state

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]) 
})
},[])

Displaying data:

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

And

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

Also displays perfectly well

But

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

This seems completely illogical to me! If yo have any insight on why this is happening, share it with me please.

解决方案

What you're seeing is the expected behavior. Loading data from Firebase (just like calling most cloud APIs) is an asynchronous operation. That's why you're passing a function (snapshot) => {...} into the operation, so that it can call you back when the operation has completed.

Until that happens, none of the code inside that function has run, so usersList will have its default value. And since you initialize the state as useState([]) its default value is [], which doesn't have a fullname member.

My best guess it that you want to set the username too after setting usersList. So:

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


Unrelated: it is more idiomatic to store the users under their UID. , instead of with push() as you do now. By using the UID as the key, you:

  1. Automatically ensure that each UID can exist only once, since keys are by definition unique in a node.
  2. Can load the user with a given UID without needing a query, which scales better if you ever reach hundreds of thousands of users.
  3. Don't need to loop in the callback anymore.

So in that case, loading the user/name becomes:

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);
  })
},[])

这篇关于在React useState中使用时未定义Firebase数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆