Reputation: 840
I want to use the React Hooks functionality in combination with Firebase. But now when the data is set, the result is only visible when the DOM is being updated. My current code is:
import React, { useState, useEffect } from 'react';
import firebase, { getPivotFunction } from '../../firebase';
/**
* Return a styled component
*/
const ListCards = () => {
const [data, setData] = useState([]);
const userListsRef = firebase
.database()
.ref('userLists')
.child('1234d343f');
useEffect(() => {
(async function() {
try {
const response = await getPivotFunction(userListsRef, 'lists');
setData(response);
} catch (e) {
console.error(e);
}
})();
}, []);
/**
* Return all list cards
*/
return (
<ul>
{data.map(item => (
<li key={item.time}>dummy text</li>
))}
</ul>
);
};
When the page is beeing rendered for the first time the 'dummy text' is not displayed, only when there is an update beeing triggered.
My goal is to let 'dummy text' apear when the page is done loading and data
not having a length of 0.
In this case getPivotFunction
contains:
/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target) => {
let dataArray = [];
ref.once('value', userInfo => {
userInfo.forEach(function(result) {
firebase
.database()
.ref(target)
.child(result.key)
.on('value', snapshot => {
dataArray.push(snapshot.val());
});
});
});
return dataArray;
};
Please let me know
Upvotes: 1
Views: 1511
Reputation: 281646
Your getPivotFunction
is an asynchronous function which relies on callback and this using async await on isn't the right approach. You instead need to have a callback
/** Get FireBase data based on a pivot table */
const getPivotFunction = (ref, target, callback) => {
const dataArray= [];
ref.once('value', userChats => {
var i = 0;
userChats.forEach(function(result) {
firebase
.database()
.ref(target)
.child(result.key)
.on('value', snapshot => {
i++;
dataArray.push(snapshot.val());
if(i === userChats.length) {
callback(dataArray)
}
});
});
});
};
and use it like
/**
* Return a styled component
*/
const ListCards = () => {
const [data, setData] = useState([]);
const userListsRef = firebase
.database()
.ref('userLists')
.child('1234d343f');
useEffect(() => {
getPivotFunction(userListsRef, 'lists', (response) => {
setData(response);
});
}, []);
/**
* Return all list cards
*/
return (
<ul>
{data.map(item => (
<li key={item.time}>dummy text</li>
))}
</ul>
);
};
Upvotes: 2
Reputation: 17239
Hooks aren't meant to work with async functions like that. Something like this should work:
const ListCards = () => {
const [data, setData] = useState([]);
const [loaded, setLoaded] = useState(false);
...
useEffect(() => {
getPivotFunction(userListsRef, 'lists')
.then(data => { setData(data); setLoaded(true)});
}, []);
};
Then only render when loaded
is true
.
Upvotes: 0