Как исправить рекурсивное обновление состояния?

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

Решение

Ты никогда не должен 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;

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

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

Другие вопросы по тегам