[英]The state updates, but doesn't show up on the page
這是 function 我用來更新我的新聞網站項目的無限滾動:
import React,{ Component } from "react";
import NewsItem from './NewsItem';
import Spinner from "./Spinner";
import PropTypes from "prop-types";
import InfiniteScroll from "react-infinite-scroll-component";
export class News extends Component {
static defaultProps={
country: "in",
pageSize: 6,
category: 'general',
totalResults: 0
}
static propTypes={
country: PropTypes.string,
pageSize: PropTypes.number,
category: PropTypes.string
}
constructor(props) {
super(props);
this.state={
articles: [],
loading: true,
page: 1
}
}
async updateNews() {
const url=`https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&apiKey=[apikey]&page=${this.props.page}&pageSize=${this.props.pageSize}`;
this.setState({ loading: true })
let data=await fetch(url);
let parsedData=await data.json()
this.setState({
articles: parsedData.articles,
totalResults: parsedData.totalResults,
loading: false
})
}
async componentDidMount() {
this.updateNews()
}
// prevClick=async () => {
// this.setState({ page: this.state.page-1 })
// }
// nextClick=async () => {
// this.setState({ page: this.state.page+1 })
// this.updateNews();
// }
fetchMoreData=async () => {
this.setState({ page: this.state.page+1 })
console.log(this.state.page)
const url=`https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&apiKey=[api key]&page=${this.props.page}&pageSize=${this.props.pageSize}`;
let data=await fetch(url);
let parsedData=await data.json()
this.setState({
articles: this.state.articles.concat(parsedData.articles),
totalResults: parsedData.totalResults
})
}
render() {
return (
<div className="container my-4">
<h2 className="my-5 text-center">Top Headlines of today!</h2>
<InfiniteScroll
dataLength={this.state.articles.length}
next={this.fetchMoreData}
hasMore={this.state.articles.length!==this.state.totalResults}
loader={<Spinner />}>
<div>
<div className="row">
{this.state.articles.map((element) => {
return <div className="col-md-4" key={element.title}>
<NewsItem title={element.title} description={element.description} imageUrl={element.urlToImage} newsUrl={element.url} author={element.author} date={element.publishedAt} />
</div>
})}
</div>
</div>
</InfiniteScroll>
</div>
)
}
}
export default News
問題是頁面 state 的更改顯示在控制台中,但是當頁面更新時,相同的數據/新聞會重復。 我嘗試使用 'this.state.page' 而不是 'this.props.page' 但我猜沒有區別。 有什么我想念的嗎?
是的,問題出在您的 fetchMoreData function 上。 state 更新工作的方式是它不會立即更新,而是將其批次的所有 state 更新並更新到下一個周期。
您可以運行此代碼以更好地理解此示例。
import react, { useState, useEffect } from "react";
const App = () => {
const [state, setstate] = useState(1);
const handleState = () => {
console.log("before", state);
setstate(state + 1);
console.log("after", state);
};
return (
<div>
<button onClick={handleState}>Check</button>
</div>
);
};
export default App;
您的問題的解決方案是從 state 中取出您的頁面大小添加 1 然后在成功調用后增加它
fetchMoreData = async () => {
let page= this.state.page + 1; // increment like this
const url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&apiKey=[api key]&page=${page}&pageSize=${this.props.pageSize}`;
let data = await fetch(url);
let parsedData = await data.json();
this.setState({
articles: this.state.articles.concat(parsedData.articles),
totalResults: parsedData.totalResults,
page: page
});
};
這是問題所在。
更新 state 時,不應使用相同的 object 或數組。 如果是這樣,則組件不知道 state 是否已更新。
所以對於第 8 行:您應該使用擴展運算符...
復制您的數組並連接該數組。
這里的問題是設置 State 並沒有發生頁面中的增量,所以訣竅是從 api Z572D4E421E5E6B9BC11D815E8A021 不同的變量中替換“this.props.page”以存儲頁面。 然后遞增它(請參閱下面的代碼以使其有意義),以便頁面稍后遞增,但我們確實獲得了正確的數據。 后來我在將基於 class 的組件轉換為基於 function 的組件時發現了這種延遲。(延遲可能仍然存在,所以只要確保通過在 Z572D4E421 中添加 1 來彌補延遲,即 55E6B71BC12A8 pageNo+1' 而不是 'pageNo' 雖然如果您使用基於 function 的帶有鈎子的組件,這將不是必需的)
變化很大,但如果我將其更改為基於 function,則頁面計數器會在 function 之外初始化,然后只需在內部遞增,因為數學遞增比使用 setState 或其他任何東西更快。 這是正確的工作代碼:
import React,{ useEffect,useState } from "react";
import NewsItem from './NewsItem';
import Spinner from './Spinner'
import PropTypes from "prop-types";
import InfiniteScroll from "react-infinite-scroll-component";
const News=(props) => {
const [articles,setarticles]=useState([])
const [loading,setloading]=useState(true)
const [page,setpage]=useState(1)
const [totalResults,settotalResults]=useState(0)
const updateNews=async () => {
const url=`https://newsapi.org/v2/top-headlines?country=${props.country}&category=${props.category}&apiKey=${props.apiKey}&page=${pageNo}&pageSize=${props.pageSize}`;
let data=await fetch(url);
let parsedData=await data.json()
setarticles(parsedData.articles)
settotalResults(parsedData.totalResults)
setloading(false)
}
useEffect(() => {
updateNews()
},[])
let pageNo=0;
const fetchMoreData=async () => {
pageNo=page+1
const url=`https://newsapi.org/v2/top-headlines?country=${props.country}&category=${props.category}&apiKey=${props.apiKey}&page=${pageNo}&pageSize=${props.pageSize}`;
let data=await fetch(url);
let parsedData=await data.json()
setarticles(articles.concat(parsedData.articles))
settotalResults(parsedData.totalResults)
setpage(pageNo)
}
return (
<>
<h1 className="text-center" style={{ margin: '35px 0px',marginTop: '90px' }}>Top Headlines of today!</h1>
<InfiniteScroll
dataLength={articles.length}
next={fetchMoreData}
hasMore={articles.length!==totalResults}
loader={<Spinner />}>
<div className="container">
<div className="row">
{articles.map((element) => {
return <div className="col-md-4" key={element.title}>
<NewsItem title={element.title} description={element.description} imageUrl={element.urlToImage} newsUrl={element.url} author={element.author} date={element.publishedAt} />
</div>
})}
</div>
</div>
</InfiniteScroll>
</>
)
}
News.defaultProps={
country: "in",
pageSize: 6,
category: 'general',
totalResults: 0
}
News.propTypes={
country: PropTypes.string,
pageSize: PropTypes.number,
category: PropTypes.string
}
export default News
感謝所有在這方面幫助過我的人,因為我能夠部分解決問題,但不能完全解決,現在它在午睡后完成。
祝你今天過得愉快!!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.