reactjs 分页组件中的页面更改后数据未正确更新

h79rfbju  于 2023-03-12  发布在  React
关注(0)|答案(1)|浏览(164)

下面是分页组件:

import React from 'react';
import classnames from 'classnames';
import { usePagination, DOTS } from './usePagination';
import './pagination.css';
const Pagination = props => {
  const {
    onPageChange,
    totalCount,
    siblingCount = 1,
    currentPage,
    pageSize,
    className
  } = props;

  const paginationRange = usePagination({
    currentPage,
    totalCount,
    siblingCount,
    pageSize
  });

  if (currentPage === 0 || paginationRange.length < 2) {
    return null;
  }

  const onNext = () => {
    onPageChange(currentPage + 1);
  };

  const onPrevious = () => {
    onPageChange(currentPage - 1);
  };

  let lastPage = paginationRange[paginationRange.length - 1];
  return (
    <ul
      className={classnames('pagination-container', { [className]: className })}
    >
      <li
        className={classnames('pagination-item', {
          disabled: currentPage === 1
        })}
        onClick={onPrevious}
      >
        <div className="arrow left" />
      </li>
      {paginationRange.map(pageNumber => {
        if (pageNumber === DOTS) {
          return <li className="pagination-item dots">&#8230;</li>;
        }

        return (
          <li
            className={classnames('pagination-item', {
              selected: pageNumber === currentPage
            })}
            onClick={() => onPageChange(pageNumber)}
          >
            {pageNumber}
          </li>
        );
      })}
      <li
        className={classnames('pagination-item', {
          disabled: currentPage === lastPage
        })}
        onClick={onNext}
      >
        <div className="arrow right" />
      </li>
    </ul>
  );
};

export default Pagination;

它被集成在review的页面中,如下所示:

import React, { useEffect, useState, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux";
import LoadingSpinner from "../Commons/LoadingSpinner";
import FeedCheckFilter from "../Commons/Filters/Filter";
import { getLimitedReviews, updateFilters } from '../../services/FiltersService';
import Review from './Review';
import Pagination from "../Commons/Pagination/Pagination";

let PageSize = 10;

const initialState = {
    limit: 10,
    offset: 0,
    reviews: [],
    count: 0
}

export default function Reviews() {
    const dispatch = useDispatch()
    const token = useSelector((state) => state.user.profile.token) 
    const username = useSelector((state) => state.user.profile.auth)
    const reviews = useSelector((state) => state.reviewsData.reviews) 
    const [currentPage, setCurrentPage] = useState(1);
    const [reviewsState, setReviewsState] = useState(initialState)
    ...
    const loadData = async (queryUrl = filters.url, limit=10, offset=0) => {
        setIsLoading(true)
        // let queryUrl = filters.url;
        if (limit || offset) {
            let action = await getLimitedReviews(token, username, queryUrl || defaultQueryUrl, limit, offset)
            setReviewsState(action.payload)
            dispatch(action)
        }
        setIsLoading(false)
    }

    const currentReviewsData = useMemo(() => {
        const firstPageIndex = (currentPage - 1) * PageSize;
        const lastPageIndex = firstPageIndex + PageSize;
        loadData(filters.url, lastPageIndex, firstPageIndex)
        if (reviews) {
            return reviews
        } else {
            return []
        }
    }, [currentPage]);

    ...
    
    useEffect(() => {
        loadData();
    }, [])
   
    ...

    return (
        <div>
            <h1>Reviews</h1>
            {isLoading ? <LoadingSpinner /> : 
                <>
                    ...
               
                    {currentReviewsData.map(item => {
                        return (<Review key={item.id} review={item} />)
                    })}

                    <Pagination
                        className="pagination-bar"
                        currentPage={currentPage}
                        totalCount={reviewsState.count}
                        pageSize={PageSize}
                        onPageChange={page => setCurrentPage(page)}
                    />
                </>
            }
        </div>
    )
}

问题是,当我按下按钮从第1页转到第2页时,评论只有在渲染后才会更新。因此,该页仍保留前一页的评论。例如,如果我在第5页,我按下按钮转到第6页。在第6页,我看到第5页的评论,现在如果我转到第7页,例如,然后我会看到第6页的评论。
这里我有一个钩子,我正在使用分页,但我认为问题不在这里:

import React from 'react';
import { useMemo } from 'react';

export const DOTS = '...';

const range = (start, end) => {
  let length = end - start + 1;
  return Array.from({ length }, (_, idx) => idx + start);
};

export const usePagination = ({
  totalCount,
  pageSize,
  siblingCount = 1,
  currentPage
}) => {
  const paginationRange = useMemo(() => {
    const totalPageCount = Math.ceil(totalCount / pageSize);

    // Pages count is determined as siblingCount + firstPage + lastPage + currentPage + 2*DOTS
    const totalPageNumbers = siblingCount + 5;

    /*
      If the number of pages is less than the page numbers we want to show in our
      paginationComponent, we return the range [1..totalPageCount]
    */
    if (totalPageNumbers >= totalPageCount) {
      return range(1, totalPageCount);
    }

    const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
    const rightSiblingIndex = Math.min(
      currentPage + siblingCount,
      totalPageCount
    );

    /*
      We do not want to show dots if there is only one position left 
      after/before the left/right page count as that would lead to a change if our Pagination
      component size which we do not want
    */
    const shouldShowLeftDots = leftSiblingIndex > 2;
    const shouldShowRightDots = rightSiblingIndex < totalPageCount - 2;

    const firstPageIndex = 1;
    const lastPageIndex = totalPageCount;

    if (!shouldShowLeftDots && shouldShowRightDots) {
      let leftItemCount = 3 + 2 * siblingCount;
      let leftRange = range(1, leftItemCount);

      return [...leftRange, DOTS, totalPageCount];
    }

    if (shouldShowLeftDots && !shouldShowRightDots) {
      let rightItemCount = 3 + 2 * siblingCount;
      let rightRange = range(
        totalPageCount - rightItemCount + 1,
        totalPageCount
      );
      return [firstPageIndex, DOTS, ...rightRange];
    }

    if (shouldShowLeftDots && shouldShowRightDots) {
      let middleRange = range(leftSiblingIndex, rightSiblingIndex);
      return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex];
    }
  }, [totalCount, pageSize, siblingCount, currentPage]);

  return paginationRange;
};
wrrgggsh

wrrgggsh1#

我认为你的备忘录不是在等待结果,所以你总是得到前一页的结果。

const currentReviewsData = useMemo(() => {
        const firstPageIndex = (currentPage - 1) * PageSize;
        const lastPageIndex = firstPageIndex + PageSize;
        loadData(filters.url, lastPageIndex, firstPageIndex)
        if (reviews) {
            return reviews
        } else {
            return []
        }
    }, [currentPage]);

在我看来,我不认为你应该使用备忘录的currentReviewsData
试试这个:

const [currentReviewsData, setCurrentReviewsData] = useState([]);

useEffect(() => {
  if (typeof currentPage !== "undefined") {
    const firstPageIndex = (currentPage - 1) * PageSize;
    const lastPageIndex = firstPageIndex + PageSize;
    loadData(filters.url, lastPageIndex, firstPageIndex).then((reviews) => {
      setCurrentReviewsData(reviews);
    });
  }
}, [currentPage]);

相关问题