反应分页查询

问题描述 投票:0回答:1

我正在为 React 项目构建分页。当我单击上一页或下一页按钮时,分页本身确实可以工作,但我有两个问题,我无法弄清楚。

  1. 浏览器按钮的行为很奇怪。我在主页(第 1 页),然后单击下一页,直到到达最后一页(第 3 页)。现在,我在第 3 页打开特定的产品页面,当我第一次单击浏览器后退按钮时,它会正确地将我返回到第 3 页,但是当我再次单击时,我希望返回到第 2 页,但我却被移出了第 3 页。完整的网站并查看我之前浏览过的其他网站。

我还在 Chrome 开发工具中收到此警告: 在简单的会话历史记录上下文中使用history.pushState,该上下文仅维护一个会话历史记录条目。看来这个警告说明了问题,但是如何保存多条历史记录呢?

  1. 如果我在浏览器中手动更改搜索查询,从 http://localhost:5173/?p=1 更改为 http://localhost:5173/?p=3 则什么也不会发生。我看到页面刷新了,我相信我的新 ?p=3 查询未以某种方式持久化,因此 useEffect 代码未运行?

代码:

  let [currentPage, setCurrentPage] = useState(getCurrentPage());
  let [pagesCount, setPagesCount] = useState(0);
  let [itemsCount, setItemsCount] = useState(0);
  let [productData, UpdateProductData] = useState([]);
  const [searchParams, setSearchParams] = useSearchParams();

  //On init
  useEffect(() => {
    getCurrentPage();
    setSearchParams({ p: `${currentPage}` });
    calcPagesCount();
    getData();
  }, []);

  //Updates screen if query is changed by browser back button or manually changing query in url bar
  useEffect(() => {
    let CurrentPageFromQuery: number;
    CurrentPageFromQuery = Number(location.search.replace(/\D/g, ""));
    setCurrentPage(CurrentPageFromQuery);
    saveCurrentPage();
    getData();
  }, [searchParams]);

  //Updates query if next/prev page buttons are clicked
  useEffect(() => {
    saveCurrentPage();
    getData();
    setSearchParams({ p: `${currentPage}` });
  }, [currentPage]);

  function prevPage() {
    if (currentPage !== 1) {
      getCurrentPage();
      setCurrentPage(currentPage - 1);
      saveCurrentPage();
    }
  }

  function nextPage() {
    if (currentPage !== pagesCount) {
      getCurrentPage();
      setCurrentPage(currentPage + 1);
      saveCurrentPage();
    }
  }

  function saveCurrentPage() {
    sessionStorage.setItem("current page", String(currentPage));
  }

  function getCurrentPage(): number {
    return Number(sessionStorage.getItem("current page") || 1);
  }

  async function calcPagesCount() {
    const api_url = `https://******&per_page=99`;
    const req = await fetch(api_url);
    const products = await req.json();
    setItemsCount(products.length);
    setPagesCount(Math.floor(products.length / 9));
  }

  async function getData() {
    const api_url = `https://******&per_page=9&page=${currentPage}`;
    const req = await fetch(api_url);
    const products = await req.json();
    UpdateProductData(products);
  }
javascript reactjs react-router pagination browser-history
1个回答
0
投票

对于您所在的页面,您应该只有单一的事实来源。在这里,您使用 URL 搜索参数和本地

currentPage
状态、,然后在其之上使用 sessionStorage。我认为你也有太多的副作用和重载的函数/处理程序/回调。

我怀疑您不需要

currentPage
状态,您可以读取和更新
p
URLSearchParameter 并与 sessionStorage 同步。

建议更改:

  • 仅当未设置
    p
    并且存在存储的会话值时,才从 sessionStorage 更新
    p
    搜索参数。
  • prevPage
    /
    nextPage
    仅更新 URL 搜索参数
  • 效果太多,使用单个效果读取当前页面并
    • 获取数据
    • 获取页数/等
    • 将当前页面保留到sessionStorage

示例:

const [searchParams, setSearchParams] = useSearchParams();

const [pagesCount, setPagesCount] = useState(0);
const [itemsCount, setItemsCount] = useState(0);
const [productData, UpdateProductData] = useState([]);

// Read current page from search params, fallback to storage
const currentPage = Number(searchParams.get("p")) ?? getCurrentPage();

// Fetch data for the current page
useEffect(() => {
  getData(currentPage);
  calcPagesCount();
  saveCurrentPage(currentPage);
}, [currentPage]);

function prevPage() {
  setSearchParams(searchParams => {
    const p = Number(searchParams.get("p")) || 1;
    searchParams.set("p", Math.max(1, p - 1));
    return searchParams;
  });
}

function nextPage() {
  setSearchParams(searchParams => {
    const p = Number(searchParams.get("p")) || 1;
    searchParams.set("p", Math.min(p + 1, pagesCount));
    return searchParams;
  });
}

function saveCurrentPage(currentPage: number) {
  sessionStorage.setItem("current page", String(currentPage));
}

function getCurrentPage(): number {
  return Number(sessionStorage.getItem("current page") || 1);
}

async function getData(currentPage: number) {
  const api_url = `https://******&per_page=9&page=${currentPage}`;
  const req = await fetch(api_url);
  const products = await req.json();
  UpdateProductData(products);
}
© www.soinside.com 2019 - 2024. All rights reserved.