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

Time:09-07

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:

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

CodePudding user response:

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.

  • Related