【问题标题】:How do I get the "results" object nested in the array "news" and map over it?如何获取嵌套在数组“news”中的“results”对象并映射它?
【发布时间】:2019-10-16 21:17:20
【问题描述】:

我正在尝试映射使用 componentDidMount 获取的数组。但是,我一直收到同样的错误“Uncaught TypeError: this.state.news.map is not a function”。

这是在 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)
    }

【问题讨论】:

  • 什么是this.state.news
  • 你做了一个console.log(data) - 我们可以看看它是什么吗?

标签: javascript arrays reactjs dictionary object


【解决方案1】:

问题是在获取数据之前调用了渲染。我建议为您的组件添加一个构造函数并将新闻初始化为一个空数组:

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

这样您的用户界面将更加用户友好。

【讨论】:

    【解决方案2】:

    在渲染期间新闻数组不存在因此它为空,解决这个问题

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

    【讨论】:

      【解决方案3】:

      这是因为在渲染时数据还没有准备好。

      您可以根据自己的需要做各种事情。

      1º。将像 state = { news: [] } 这样的默认状态声明为空数组。

      2º。在渲染方法中渲染某种加载,例如if (!this.state.news.length) { return "Loading..." }

      我看到你在每个新闻项目中都有数组,所以你也应该控制它。

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

      看,您将 setState data 设置为 news 作为对象属性,然后您尝试使用 map 对其进行迭代。你不能这样做。

      【讨论】:

        【解决方案4】:

        因为this.state.news 是一个对象。在您的setState 中,我认为您期待的是data.results(这是一个数组),而不仅仅是data

        this.setState({
          news: data.results,
          loading: false
        });
        

        【讨论】:

          猜你喜欢
          • 2021-09-30
          • 2021-07-26
          • 2022-08-10
          • 2021-02-08
          • 2023-01-23
          • 1970-01-01
          • 2021-12-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多