如何解决递归更新状态?

时间:2019-02-08 07:55:11

标签: reactjs react-lifecycle

我正在使用newsapi建立一个应用程序。我的状态面临两个问题。我使用api提取数据并将其分配给我的状态。并在我看来使用它。

问题1

我的视图在应用程序接收数据之前就已呈现。

问题2

当我尝试在新的获取后更新状态时。它会一次又一次地递归更新数据集。

import React, {Component} from 'react';
import NewsComponent from './NewsComponent/NewsComponent'

class News extends Component {
    state = {
        displayStatus: false,
        newsItems: []
    };

    toogleDisplayHandler = () => {
        if(this.state.displayStatus===true){
        this.setState({displayStatus:false})
        }
        else{
        this.setState({displayStatus:true})
        }
    }

    render(){   
        const NewsAPI = require('newsapi');
        const newsapi = new NewsAPI('d6da863f882e4a1a89c5152bd3692fb6');
        //console.log(this.props.keyword);
        newsapi.v2.topHeadlines({
            sources: 'bbc-news,abc-news',
            q: this.props.keyword
        }).then(response => {
            //console.log(response)
            response.articles.map(article => {
                //console.log(article);
                return(
                    //console.log(this.state.newsItems)
                    this.setState({
                        newsItems: [...this.state.newsItems, article],
                    })
                    //this.state.newsItems.push(article)

                )
            });
        });

        let Article = null;    

        Article = (
            <div>
                {
                this.state.newsItems.map((news, index) => {
                    return (
                    <NewsComponent key={index}
                        title={news.title}
                        url={news.url}
                        description={news.description}
                        author={news.author}
                        publish={news.publishedAt}
                        image={news.urlToImage}
                    />
                    )
                })
                }
            </div>
        )

    return (
        <div className="App">

            {Article}

            <button onClick={this.toogleDisplayHandler}>
                {this.state.displayStatus === true ? "Hide Article" : "Display Articles"}
            </button>
        </div>

    )
    }

}

export default News;

请帮助我解决此问题。

2 个答案:

答案 0 :(得分:3)

永远不要在setState中使用render,因为那样会导致无限循环。在componentDidMountconstructor中进行操作。

我还建议不要使用map来简单地遍历列表。 Array.map是一个函数,可用于返回通过迭代另一个数组而构建的数组。如果要为数组的每个元素运行一些代码,请使用Array.forEach

赞:

import React, { Component } from "react";
import NewsComponent from "./NewsComponent/NewsComponent";

class News extends Component {
  state = {
    displayStatus: false,
    newsItems: []
  };

  toogleDisplayHandler = () => {
    if (this.state.displayStatus === true) {
      this.setState({ displayStatus: false });
    } else {
      this.setState({ displayStatus: true });
    }
  };

  componentDidMount = () => {
    const NewsAPI = require("newsapi");
    const newsapi = new NewsAPI("d6da863f882e4a1a89c5152bd3692fb6");

    newsapi.v2
      .topHeadlines({
        sources: "bbc-news,abc-news",
        q: this.props.keyword
      })
      .then(response => {
        response.articles.forEach(article => {
          this.setState({
            newsItems: [...this.state.newsItems, article]
          });
        });
      });
  };

  render() {
    let Article = null;

    Article = (
      <div>
        {this.state.newsItems.map((news, index) => {
          return (
            <NewsComponent
              key={index}
              title={news.title}
              url={news.url}
              description={news.description}
              author={news.author}
              publish={news.publishedAt}
              image={news.urlToImage}
            />
          );
        })}
      </div>
    );

    return (
      <div className="App">
        {Article}

        <button onClick={this.toogleDisplayHandler}>
          {this.state.displayStatus === true
            ? "Hide Article"
            : "Display Articles"}
        </button>
      </div>
    );
  }
}

export default News;

答案 1 :(得分:1)

1)您可以添加一个检查,即您的状态是否具有要在屏幕上显示以呈现视图的数据。

2)请使用 ComponentDidMount 反应生命周期功能从外部源获取数据并在状态下更新此数据。在Render方法中,它将继续递归调用它。