Как я могу отобразить несколько компонентов, интерполирующих JSX?

#javascript #reactjs #jsx

#javascript #reactjs #jsx

Вопрос:

Я работаю над веб-сайтом, который использует API от NYT, и я застрял, пытаясь отобразить всю информацию, которая у меня есть, для отображения необходимой информации (ссылки на изображения в формате JPG, ссылки на статьи, названия статей, даты статей).

У меня вся моя информация хранится в переменной с именем postNY и извлекается вся информация (из API) в эти массивы:

 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
})
 

Тогда вот где возникает моя проблема. Я пытаюсь отобразить такую информацию в 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>
        
    )
 

Это ничего не возвращает на сайт. Я застрял на том, как реализовать отображение ВСЕХ этих вещей в массиве на сайте. Каждый массив упорядочен правильно, то, что я пытаюсь отобразить на сайте, это (в каждый из их собственных контейнеров):

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]

И Т.Д…

Есть ли какие-либо подходы, которые я могу предпринять?

Вот полный код:

 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
 

Комментарии:

1. Вы делаете это странным образом. useState находится в функциональном компоненте, который вы не можете вызвать setPostNY . Можете ли вы показать полный код функционального компонента. Где находится renderEverything по отношению к useState функции. находятся renderEverything const [postNY, setPostNY] ли они в одном и том же функциональном компоненте. objArr Откуда это взялось. можете ли вы отредактировать свой пост, чтобы мы могли лучше понять, что происходит.

2. ^^ @MrBrN197 высказывает обоснованную точку зрения. Нам нужно увидеть полный код. Однако, судя по тому, что вы показываете, renderEverything, похоже, не имеет доступа к postNY. Если render everything является функцией в рендеринге, это должна быть функция обратного вызова, и вам нужно определить массив зависимостей, передав ему postNY. Если функция не просматривает зависимости, она никогда не обновит эти значения зависимостей.

3. @MrBrN197 и Jason Я добавил полный код в конец сообщения

Ответ №1:

Убедитесь, что вы действительно вызываете функцию, которая возвращает содержимое. у вас {renderEverything} это должно быть {renderEverything()}

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

Также useEffect укажите пустой массив зависимостей, чтобы он запускался один раз, иначе он будет выполняться непрерывно.

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

просто как примечание, использование Object.entries делает код, который вы пишете, довольно подробным. javascript имеет множество функций, которые упрощают итерацию объектов и массивов. Вам не нужно использовать индексацию, когда вы можете произнести имя объекта.
вы можете преобразовать это

 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)
    })
}
 

к этому

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