'setState not updating react component properly

I am trying to add pagination in React and am sending a query for it, based on the page number of the URL. The data should be fetched and update the same component.

But the problem occurs when I go from page 2 to page 3. The data from page 2 data and page 3 data are shown alternately for a while.

Enter image description here

After some time, the newly fetched data is updated. I have setPost([]) after page 3 is clicked, but I don't know from where page 2 is coming.

I want to setLoading to true till the newly fetched data is completely fetched.

const Daily = ({match}) => {

    const [posts, setPosts] = useState([]);
    const [numberOfPages, setNumberOfPages] = useState([]);
    const [loading, setLoading] = useState(true);
    const perPageItems = 8;

    useEffect(() => {
        const totalPost = () => {
            getPostsCount()
            .then(data => {
                setNumberOfPages(Math.ceil(data/perPageItems))
            })
        }

        const loadIndexPosts = (a, b) => {
            getPostsByIndex(a, b)
            .then(data => {
                if (data.error) {
                    console.log(data.error);
                } else {
                    setPosts(data);
                }
                setLoading(false);
            })
        };

        totalPost()
        if(match.params.page==undefined)
            match.params.page=1;
         var n = parseInt(match.params.page)-1;
         var startIdx = n*perPageItems;
         loadIndexPosts(startIdx, perPageItems)
    },)

    console.log(posts);

    return (

        <div>
            <div className="mt-5 daily-card-feed">
                {loading && <ThreeDotsWave/>}
                {posts.map((post, index) => {
                    return (
                        <div key={index}>
                            <DailyCard post={post}/>
                        </div>
                    )
                })}
            </div>


            <div className="h4 pb-5 pull-right mr-5">
                {match.params.page==1 &&
                    <Link to={`/daily/page/2`} onClick={() => {setLoading(true); setPosts([])}}>Older Post -></Link>}
                {match.params.page!=1 &&
                     <Link to={`${parseInt(match.params.page)+1}`} onClick={() => {setLoading(true); setPosts([])}}>Older Post -></Link>}
            </div>

        </div>
    )

}


Solution 1:[1]

First of all, let's figure out the logic of loading new data. When a new page arrives at path, you want to call the api. I think the problem is here:

useEffect(() => { 
    const totalPost = () => {
        getPostsCount()
        .then(data => {
            setNumberOfPages(Math.ceil(data/perPageItems))
        })
    }

    const loadIndexPosts = (a, b) => {
        getPostsByIndex(a, b)
        .then(data => {
            if (data.error) {
                console.log(data.error);
            } else {
                setPosts(data);
            }
            setLoading(false);
        })
    };

    totalPost()
    if(match.params.page==undefined)
        match.params.page=1;
     var n = parseInt(match.params.page)-1;
     var startIdx = n*perPageItems;
     loadIndexPosts(startIdx, perPageItems)
},)

We can break this like:

const totalPost = () => {
        getPostsCount()
        .then(data => {
            setNumberOfPages(Math.ceil(data/perPageItems))
        })
    }
const loadIndexPosts = (a, b) => {
    getPostsByIndex(a, b)
    .then(data => {
        if (data.error) {
            console.log(data.error);
        } else {
            setPosts(data);
        }
        setLoading(false);
    })
};

useEffect(() => { 
if(match.params.page==undefined)
    match.params.page=1;
 var n = parseInt(match.params.page)-1;
 var startIdx = n*perPageItems;
 loadIndexPosts(startIdx, perPageItems)
},[numberOfPages])

This will add the dependency of the call when page number changes. And call totalPost() only from click event.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1