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