'how to load components with database data

I am trying to fill a component with database data - I have an image and some description that is fetched from Google Firestore. At the moment I am struggling because the component is being rendered before the data is fetched and put into the components.

My code is listed below. It is in another file and then is run in the file I want to display the data in. I also know that my data is being fetched from the database correctly because I am printing to the console and when I run the code, the right data is displayed in the console.

Thanks!

function DailyView({itemImage, itemEmotion, itemReason, itemMood, itemTime}) {

    const db = getDatabase();
    const getEmotions = ref(db, 'users/' + global.uid);
    onValue(getEmotions, (snapshot)=>{
        var data = snapshot.val();

        for (const value of Object.values(data)) {
            console.log(value["entry"]["feeling"])
          }

        const numEntries = Object.keys(data).length
        console.log(numEntries)

        console.log(Object.values(data)[0]["entry"]["reason"])
        global.item1Emotion = Object.values(data)[numEntries-1]["entry"]["feeling"]
        global.item1Reason = Object.values(data)[numEntries-1]["entry"]["reason"]
        global.item1Mood = Object.values(data)[numEntries-1]["entry"]["mood"]
        global.item1Time = Object.values(data)[numEntries-1]["entry"]["time"]
        global.item1Time = Moment(global.item1Time).format('D MMM YYYY - h:mma ')
        global.item1Image = getImage(global.item1Emotion)



        

    })



    return (


        <View style={styles.viewStyle}>
                <Image style={styles.emotions} source={global.item1Image}/>
                <View style={styles.ViewReasons}>
                    <Text style={styles.emotionText}>{global.item1Emotion}</Text>
                    <Text style={styles.emotionSub}>Reason: {global.item1Reason}</Text>
                    <Text style={styles.emotionSub}>Mood: {global.item1Mood}</Text>
                    <Text style={styles.emotionSub}>{global.item1Time}</Text>
                </View>
        </View>

    );
}


Solution 1:[1]

You can use a boolean state to prevent rerender of component until data is fetched. Sample code:

const [loading, setLoading] = useState(false);

return (
{loading ? (
//Your code
):(
//Custom no data found component or something like that
)}
) 

Solution 2:[2]

You can use a state to store the data from firestore and check if it is undefined. If so return nothing otherwise display the data.

const [data, setData] = useState()

...

if (!data) {
   return <></>
}

return (
    <View>
        <Text>{data.text}</Text>
    </View>
)

Solution 3:[3]

You should look into React Suspense, it was created exactly to address your issue.

https://reactjs.org/docs/concurrent-mode-suspense.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tafsir Ahamed
Solution 2 Mointy
Solution 3 Samson