Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I display data pulled from Firebase in React components?

I am working on a website and learning React and Firebase. I am able to pull data from Firebase and display it on the page using a map and returning a div for each element however I would like all the information pulled to be displayed in a component I created for them to have consistent styling with the rest of the page.

When trying to cycle through the posts array, I get an error saying Cannot read properties of undefined (reading 'id') however when I console.log the array all the objects are displayed correctly. Is there a way to access the array by index or am I going about this the wrong way?

Here is the MRE:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import React, { useState, useEffect } from 'react'
import { TrendBar, TrendCard } from '../components'
import { db } from '../firebase'
import { collection, getDocs } from 'firebase/firestore'

const Home = () => {
    const [posts, setPosts] = useState([]);
    const collectionRef = collection(db, 'posts');

    useEffect(() => {
        const getPosts = async () => {
            const data = await getDocs(collectionRef)
            setPosts(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })))
        }
        getPosts()
    }, [])

    return (

        <>
        {/* displays all elements of the db on the page  */}
        {posts.map((post) => {
            return <div>
                <h1>{post.title}</h1>
            </div>
        })}

        {/* Would like to display the elements like this */}
            <TrendBar
                firstTrend={
                    <TrendCard
                        id={posts[0].id}
                        image={posts[0].image}
                        imageAlt={posts[0].imageAlt}
                        title={posts[0].title}
                        tags={posts[0].tags}
                    />
                  }
                secondTrend={
                    <TrendCard
                        id={posts[1].id}
                        image={posts[1].image}
                        imageAlt={posts[1].imageAlt}
                        title={posts[1].title}
                        tags={posts[1].tags}
                    />
                 }
            />
        </>
    )
}

Thank you

>Solution :

You need to check the array.length !== 0 before drawing it.
There are several ways how you can check it, the simplest one is that:

posts.length && posts.map((post) => {
                return <div>
                    <h1>{post.title}</h1>
                </div>
            })}

posts?.map((post) => {
            return <div>
                <h1>{post.title}</h1>
            </div>
        })}

Also, to prevent errors in the future, we have the new syntax:

<TrendBar
            firstTrend={
                <TrendCard
                    **id={posts?.[0].id}**
                    image={posts[0].image}
                    imageAlt={posts[0].imageAlt}
                    title={posts[0].title}
                    tags={posts[0].tags}
                />

Optional calls, you can call event function in that way func?.().

You need to do those checks because the data is coming asynchronously, so you can’t get array[n] elem before array is downloaded.

If you have more questions, don’t hesitate to ask.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading