Как получить объект «results», вложенный в массив «news», и отобразить его? - PullRequest
1 голос
/ 31 мая 2019

Я пытаюсь отобразить массив, который выбирается с помощью componentDidMount.Тем не менее, я продолжаю получать ту же ошибку «Uncaught TypeError: this.state.news.map не является функцией».

Это на componentDidMount

componentDidMount() {
        fetch(
            "https://content.guardianapis.com/search?api-key=test"
        )
            .then(response => response.json())
            .then(data => {
                this.setState({
                    news: data
                })
                console.log(data)
            })
    }

Это моя функция для сопоставленияповерх данных

renderNews() {
        return this.state.news.map((a, i) => (
            <div key={i}>
                {a.response.map((b, i) => (
                    <div key={i}>
                        <div key={i} className="newsEach">
                            <h3>{b.webTitle}</h3>
                            <ul className="newsInfoUl">
                                <li className="newsInfoEach">{b.type}</li>
                                <li className="newsInfoEach">
                                    {b.sectionName}
                                </li>
                                <li className="newsInfoEach">{b.pillarName}</li>
                                <li className="newsInfoEach">{b.webUrl}</li>
                            </ul>
                        </div>
                    </div>
                ))}
            </div>
        ))
    }

Затем я отображаю данные здесь

render() {
        return (
            <div className="newsWrapper">
                {/* <h3>{this.renderNews()}</h3> */}
                <h3>Hello</h3>
            </div>
        )
    }

Обновление # 1 Вот данные, которые я получил из console.log (data)

{response: {…}}
response:
currentPage: 1
orderBy: "newest"
pageSize: 10
pages: 211707
results: Array(10)
0: {id: "business/live/2019/may/31/markets-trump-shock-mexi…ffs-trade-war-china-brexit-ftse-100-business-live", type: "liveblog", sectionId: "business", sectionName: "Business", webPublicationDate: "2019-05-31T08:25:12Z", …}
1: {id: "football/2019/may/31/atletico-madrid-stadium-wanda…litano-champions-league-final-liverpool-tottenham", type: "article", sectionId: "football", sectionName: "Football", webPublicationDate: "2019-05-31T08:23:15Z", …}
2: {id: "tv-and-radio/2019/may/31/a-sinister-tale-from-the-minds-behind-dirty-john-podcasts-of-the-week", type: "article", sectionId: "tv-and-radio", sectionName: "Television & radio", webPublicationDate: "2019-05-31T08:12:02Z", …}
3: {id: "politics/2019/may/31/alastair-campbell-labour-expulsion-discrimination-appeal", type: "article", sectionId: "politics", sectionName: "Politics", webPublicationDate: "2019-05-31T08:11:22Z", …}
4: {id: "football/from-the-archive-blog/2019/may/31/womens-football-match-crouch-end-1895", type: "article", sectionId: "football", sectionName: "Football", webPublicationDate: "2019-05-31T08:00:27Z", …}
5: {id: "culture/2019/may/31/what-to-see-this-week-in-the-uk", type: "article", sectionId: "culture", sectionName: "Culture", webPublicationDate: "2019-05-31T08:00:27Z", …}
6: {id: "tv-and-radio/2019/may/31/when-they-see-us-review-netflix-ava-duvernay-central-park-five", type: "article", sectionId: "tv-and-radio", sectionName: "Television & radio", webPublicationDate: "2019-05-31T08:00:27Z", …}
7: {id: "music/2019/may/31/lee-scratch-perry-rainford-review-on-u-sound-records", type: "article", sectionId: "music", sectionName: "Music", webPublicationDate: "2019-05-31T08:00:27Z", …}
8: {id: "books/2019/may/31/mother-ship-francesca-segal-review", type: "article", sectionId: "books", sectionName: "Books", webPublicationDate: "2019-05-31T07:58:27Z", …}
9: {id: "football/2019/may/31/football-transfer-rumours-spurs-to-bid-for-wilfried-zaha", type: "article", sectionId: "football", sectionName: "Football", webPublicationDate: "2019-05-31T07:47:36Z", …}
length: 10
__proto__: Array(0)
startIndex: 1
status: "ok"
total: 2117063
userTier: "developer"
__proto__: Object
__proto__: Object

Извините, я забыл включить эту часть своего кода, с которой я инициализирую this.state.news.Вот оно

constructor() {
        super()

        this.state = {
            news: []
        }

        this.renderNews = this.renderNews.bind(this)
    }

Ответы [ 4 ]

1 голос
/ 31 мая 2019

Проблема в том, что render вызывается до того, как данные извлекаются.Я бы предложил добавить конструктор к вашему компоненту и инициализировать новости в пустой массив:

constructor() {
  super();
  this.state = {
    news: []
  };
}

И если вы хотите сделать это правильно, вы можете добавить свойство загрузки в ваше состояние:

constructor() {
  super();
  this.state = {
    loading: true,
  };
}

componentDidMount() {
  fetch('https://content.guardianapis.com/search?api-key=test')
    .then(response => response.json())
    .then(data => {
      this.setState({
        news: data,
        loading: false,
      });
      console.log(data);
    });
}

render() {
  const { loading } = this.state;
  return (
    <div>
      {loading ? (
        <h1>Loading...</h1> {/* Or use a loading icon or gif */}
      ) : (
        <div className="newsWrapper">
          <h3>{this.renderNews()}</h3>
        </div>
      )}
    </div>
  );
}

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

1 голос
/ 31 мая 2019

во время рендеринга массив новостей отсутствует, следовательно, он нулевой, чтобы решить это

renderNews() {
        const { news = [] } = this.state; // assign a default value
        return news.map((a, i) => (
            <div key={i}>
                {a.response.map((b, i) => (
                    <div key={i}>
                        <div key={i} className="newsEach">
                            <h3>{b.webTitle}</h3>
                            <ul className="newsInfoUl">
                                <li className="newsInfoEach">{b.type}</li>
                                <li className="newsInfoEach">
                                    {b.sectionName}
                                </li>
                                <li className="newsInfoEach">{b.pillarName}</li>
                                <li className="newsInfoEach">{b.webUrl}</li>
                            </ul>
                        </div>
                    </div>
                ))}
            </div>
        ))
    }
1 голос
/ 31 мая 2019

Это происходит потому, что во время рендеринга данные еще не готовы.

Вы можете делать разные вещи в зависимости от ваших потребностей.

1º. Объявите состояние по умолчанию, например state = { news: [] }, как пустой массив.

2 °. Рендеринг некоторой загрузки в методе рендеринга, такой как if (!this.state.news.length) { return "Loading..." }

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

state = { news: { data: [] } }

Смотри, вы устанавливаете в setState data новости как свойство объекта, а затем пытаетесь перебрать их с картой. Вы не можете сделать это так.

0 голосов
/ 31 мая 2019

Потому что this.state.news это объект.В вашем setState, я думаю, вы ожидаете data.results (который является массивом) вместо просто data.

this.setState({
  news: data.results,
  loading: false
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...