Как исправить рекурсивное обновление состояния? - PullRequest
0 голосов
/ 08 февраля 2019

Я создаю приложение, используя 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 голосов
/ 08 февраля 2019

1) Вы можете добавить проверку, если в вашем штате есть данные, которые вы хотите отобразить на экране для визуализации представления.

2) Пожалуйста, используйте ComponentDidMount Реагирует на функцию жизненного цикла, чтобыполучить данные из внешнего источника и обновить эти данные в состоянии.В методе Render он будет продолжать вызывать его рекурсивно.

0 голосов
/ 08 февраля 2019

Вы никогда не должны setState в render, поскольку это вызовет бесконечный цикл.Сделайте это в componentDidMount или constructor.

Я бы также рекомендовал не использовать карту для простой итерации по списку.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;

...