简体   繁体   中英

How can I render multiple components interpolating JSX?

I am working on a website that uses an API from NYT and I am stuck trying to render all the info I have to display necessary info needed (JPG image links, links to the articles, titles to the articles, the dates to the articles).

I have all my info stored in a variable called postNY and retrieved all info(from API) into these arrays:

const [postNY, setPostNY] = useState({
    images: [],
    links: [],
    titles: [],
    sections: [],
    dates: [],
    summaries: []
})
// NOTE: OBJARR IS FROM API
// GET IMG
var imgs = []
for (var key in Object.entries(objArr)[3][1]) {
    var obj = Object.entries(objArr)[3][1][key]
    Object.entries(obj['media']).forEach(elem => {
        imgs.push(elem[1]['media-metadata'][2].url)
    }
    )
}

// GET LINKS
var urls = []
Object.entries(objArr)[3][1].forEach(elem => urls.push(elem.url))


// GET TITLES
var titles = []
Object.entries(objArr)[3][1].forEach(elem => titles.push(elem.title))


// GET SECTION TAG
var sections = []
Object.entries(objArr)[3][1].forEach(elem => sections.push(elem.section))


// GET PUBLISHED DATE
var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
var dates = []
Object.entries(objArr)[3][1].forEach(elem => {
    var myDate = new Date(elem.published_date);
    dates.push(myDate.toLocaleDateString("en-US", options))
})


// GET BRIEF SUMMARIES
var summaries = []
Object.entries(objArr)[3][1].forEach(elem => summaries.push(elem.abstract));


// setPostNY
setPostNY({
    images: imgs,
    links: urls,
    titles: titles,
    sections: sections,
    dates: dates,
    summaries: summaries
})

Then this is where my problem occurs. I try to render the info like this into JSX:

const renderEverything = () => {
    const renderImgs = postNY.images.map((img) => <img src={img}></img>)
    const renderSummaries = postNY.summaries.map((summary) => <p className="desc">{summary}</p>)
    const renderLinks = postNY.links.map((link) => <p>{link}</p>)
    const renderTitles = postNY.titles.map((title) => <h2>{title}</h2>)
    const renderDates = postNY.dates.map((date) => <p>{date}</p>)
    const renderSections = postNY.sections.map((section) => <a href="#">{section}</a>)

    return (
        <div className="container">
            {renderImgs}
            {renderSummaries}
            {renderLinks}
            {renderTitles}
            {renderDates}
            {renderSections}
        </div>
    )
}

JSX:

return (
        <div className="page-content">
            
            {renderEverything}
            
        </div>
        
    )

This returns nothing to the site. I am stuck on how to implement showing ALL these things in the array onto the site. Each array is ordered correctly, what I am trying to display on the site is this(into each of their own containers):

1: postNY.images[0], postNY.links[0], postNY.titles[0], postNY.sections[0], postNY.dates[0], postNY.summaries[0]

2: postNY.images[1], postNY.links[1], postNY.titles[1], postNY.sections[1], postNY.dates[1], postNY.summaries[1]

ETC...

Are there any approaches I can take?

Here is the full code:

import React, {useState,useEffect} from 'react'
import '../PageContent/PageContent.css'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import { faThumbsUp, faHeart} from '@fortawesome/free-solid-svg-icons'



const PageContent = (props) => {


    const [postNY, setPostNY] = useState({
        images: [],
        links: [],
        titles: [],
        sections: [],
        dates: [],
        summaries: []
    })


    useEffect(() => {
        fetch("https://api.nytimes.com/svc/mostpopular/v2/viewed/1.json?api-key=uCErKitNpdG7E7ma9rT0IxEGZ4xKs8Vw")
        .then((res) => res.json())
        .then((objArr)=>{

            // GET IMG
            var imgs = []
             for (var key in Object.entries(objArr)[3][1]) {
                var obj = Object.entries(objArr)[3][1][key]
                Object.entries(obj['media']).forEach(elem => 
                {
                    imgs.push(elem[1]['media-metadata'][2].url)
                }
                    ) 
            }
            
             // GET LINKS
            var urls = []
            Object.entries(objArr)[3][1].forEach(elem => urls.push(elem.url))
            

            // GET TITLES
            var titles = []
            Object.entries(objArr)[3][1].forEach(elem => titles.push(elem.title))
            

            // GET SECTION TAG
            var sections = []
            Object.entries(objArr)[3][1].forEach(elem => sections.push(elem.section))
            
            
            // GET PUBLISHED DATE
            var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
            var dates = []
            Object.entries(objArr)[3][1].forEach(elem => 
               { 
                   var myDate  = new Date(elem.published_date); 
                   dates.push(myDate.toLocaleDateString("en-US", options))
                }
                )
            

            // GET BRIEF SUMMARIES
            var summaries = []
            Object.entries(objArr)[3][1].forEach(elem => summaries.push(elem.abstract));
            
            setPostNY({
                images: imgs,
                links: urls,
                titles: titles,
                sections: sections,
                dates: dates,
                summaries: summaries
            })
        })
        
        
    })

    const renderEverything = () => {
        const renderImgs = postNY.images.map((img) => <img src={img}></img>)
        const renderSummaries = postNY.summaries.map((summary) => <p className="desc">{summary}</p>)
        const renderLinks = postNY.links.map((link) => <p>{link}</p>)
        const renderTitles = postNY.titles.map((title) => <h2>{title}</h2>)
        const renderDates = postNY.dates.map((date) => <p>{date}</p>)
        const renderSections = postNY.sections.map((section) => <a href="#">{section}</a>)

        return (
            <div className="container">
                {renderImgs}
                {renderSummaries}
                {renderLinks}
                {renderTitles}
                {renderDates}
                {renderSections}
            </div>
        )
    }
        
        
        

        
        
        
    
    

    return (
        <div className="page-content">
            
            {renderEverything}
            
        </div>
        
    )
}

export default PageContent

Make sure you are actually calling the function that returns the content. you have {renderEverything} it should be {renderEverything()}

    return (
        <div className="page-content">
            {renderEverything()}
        </div>
    )

Also on useEffect provide an empty array of dependencies to make it run once otherwise it will run continuously.

useEffect(() => {
    // your fetch code
}, []) // add this

just as a note, using Object.entries makes the code you are writing quite verbose. javascript has a lot of features that make it easy to iterate objects and Arrays. You don't have to use indexing when you can say the name of the object. you can convert this

var imgs = []
for (var key in Object.entries(objArr)[3][1]) {
    var obj = Object.entries(objArr)[3][1][key]

    Object.entries(obj['media']).forEach(elem => {
        imgs.push(elem[1]['media-metadata'][2].url)
    })
}

to this

let imgs = objArr.results.map( (entry) => entry.media?.[0]?.['media-metadata'][2].url )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM