Reputation: 1556
I'm trying to show a list of users, I get from Firebase Realtime Database. On the logs I get them all! But on the screen, only the first one appears. If I put as a dependency users
I get an infinite loop on the logs but still one item on the screen. useCallback
didn't help either. If I fill in the inputs on the screen, thus trigger a re-render, then I get all the users. Why doesn't it get them all on the first place? Could it be something with Typescript?
Thanks!
...
const [users, setUsers] = useState<any[]>([]);
const [usersRef] = useState<any>(firebase.database().ref().child('users'));
...
const getUsers: () => void = useCallback(() => {
const loadedUsers: any[] = []
usersRef.on('child_added', (snap: any) => {
loadedUsers.push(snap.val())
setUsers(loadedUsers)
console.log('loadedUsers', loadedUsers);
})
}, [setUsers, usersRef])
useEffect(() => {
getUsers();
return () => usersRef.off()
}, [usersRef, getUsers])
const displayUsers = (users: any) => {
console.log(users);
return users.length > 0 && users.map((user: any) =>
<li key={user.id}>
{user.email}
</li>
)
}
...
<ul>
{displayUsers(users)}
</ul>
So, thanks to @Renaud Tarnec, it turned out to be a problem with the firebase listener. I had to listen on value
change instead of child_added
. Below is the new version. I don't really like the way displayUsers
turned out to be, but it works. If any has any suggestions, I would be happy to see.
Thanks again!
const getUsers: () => void = useCallback(() => {
const loadedUsers: any[] = []
usersRef.on('value', (snap: any) => {
loadedUsers.push(snap.val())
setUsers(loadedUsers)
console.log('loadedUsers', loadedUsers);
})
}, [setUsers, usersRef])
...
const displayUsers = (users: any) => {
console.log(users);
return users.length > 0 && users.map((userObj: any) => {
const users = []
for (const key in userObj) {
users.push(userObj[key])
}
return users.map((user: any) =>
<li key={user.id}>
{user.email}
</li>
)
}
)
}
Upvotes: 0
Views: 50
Reputation: 83163
If I correctly understand your problem, this is because you use the child_added
event instead of the value
one. See the difference between the two in the doc:
value event
This event will trigger once with the initial data stored at this location, and then trigger again each time the data changes. The DataSnapshot passed to the callback will be for the location at which
on()
was called..child_added event
This event will be triggered once for each initial child at this location, and it will be triggered again every time a new child is added. The DataSnapshot passed into the callback will reflect the data for the relevant child.
In summary, with the value
event you get all the data at this location, while with the child_added
event you get the data of the child.
Upvotes: 1