簡體   English   中英

state 更新,但未顯示在頁面上

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM