在设计任何网站时,我们需要考虑如何显示我们的数据,以便我们的用户可以正确使用它并且不会被它淹没。数据组织得越好,网站的用户体验就越好。

分页是实现这一目标的一种方法。它是一种将 Web 内容划分为离散页面的方法,从而以有限且易于消化的方式呈现内容。

在这篇博客中,我们将制作一个简单的反应应用程序,我们将从这个https://jsonplaceholder.typicode.com/postsAPI 获取数据并以分页格式显示。

在这里,我们将一次获取所有数据,然后将其显示在页面中,但是使用后端您可以为每个页面获取小块数据,两种方法的前端分页代码将保持不变。

1.设置文件

2.写代码取数据

3.编写分页组件

4.把整个代码放在一起

让我们开始吧!

1.设置文件

使用 create react app 模板创建一个 react 应用

npx create-react-app pagination-app

进入全屏模式 退出全屏模式

或者您也可以在codesandboxstackblitz上编码

创建应用程序后,您的文件夹结构可能如下所示

[react app的文件夹结构](https://res.cloudinary.com/practicaldev/image/fetch/s--zmrgB2jU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/uploads/articles/72govg69m2c9zwohsxzy.png)

2\。编写代码以获取数据

我们将使用fetchAPI 从 jsonplaceholder API 中获取数据并将其存储在一个状态中。从App.js文件中删除所有代码并编写下面给出的代码

import { useState } from "react";

const URL = "https://jsonplaceholder.typicode.com/posts";

function App() {
  const [posts, setPosts] = useState([]);
  useEffect(() => {
    fetch(URL)
      .then((response) => {
        if (response.ok) return response.json();
        throw new Error("could not fetch posts");
      })
      .then((posts) => setPosts(posts))
      .catch((error) => console.error(error));
  },[]);
  return <div className="App"></div>;
}

export default App;

进入全屏模式 退出全屏模式

在这里,我们在useEffect钩子中编写了 fetch 函数并传递了一个空的依赖数组,这将确保我们的 fetch 函数在页面加载后只运行一次。如果数据获取成功,则将其存储在状态中,否则将在控制台中显示错误。

如果您想了解更多关于fetch的工作原理,可以阅读我的博客Fetch API: Basics

3\。编写分页组件

现在,在获取数据后,我们将编写分页组件。

在您的 src 文件夹中创建一个文件Pagination.js

我们将每页显示 5 个帖子,这将是我们的页数限制。我们会将当前页码存储在一个状态中,并使用 PreviousNext 按钮对其进行更新,我们还将显示 3 个连续的页码,即上一个、当前和下一个。

import React, { useState, useEffect } from "react";

const Pagination = ({ pageDataLimit, posts }) => {
  const [currPageNo, setCurrPageNo] = useState(1);
  const [currPagePosts, setCurrPagePosts] = useState([]);
  const [pageNumberGroup, setPageNumberGroup] = useState([]);

  useEffect(() => {
    setCurrPagePosts(getPageData());
    setPageNumberGroup(getPageNumberGroup());
    console.log("run");
  }, [posts, currPageNo]);

  const nextPage = () => setCurrPageNo((prev) => prev + 1);
  const previousPage = () => setCurrPageNo((prev) => prev - 1);
  const changePageTo = (pageNumber) => setCurrPageNo(pageNumber);
  const getPageData = () => {
    const startIndex = currPageNo * pageDataLimit - pageDataLimit;
    const endIndex = startIndex + pageDataLimit;
    return posts.slice(startIndex, endIndex);
  };
   const getPageNumberGroup = () => {
    let start = Math.floor((currPageNo - 1) / 3) * 3;
    console.log(new Array(3).fill(" ").map((_, index) => start + index + 1));
    return new Array(3).fill(" ").map((_, index) => start + index + 1);
  };
return (
    <div></div>
  );
};

export { Pagination };

进入全屏模式 退出全屏模式

在这里,我们的分页组件将postspage limit作为道具。getPageData函数将用于计算要在每个页面中显示的帖子。使用开始和结束索引,我们将对帖子数组进行切片并更新currPagePosts状态。

getPageNumberGroup功能用于显示上一页、当前页码和下一页页码。

现在,我们将映射currPagePostspageNumberGroup状态以显示帖子。

return (
    <div>
      <h1 className="heading">Posts in Pagination</h1>
      <ul className="posts-container list-style-none">
        {currPagePosts.map(({ id, title, body }) => {
          return (
            <li key={id} className="post">
              <h3>{title}</h3>
              <p>{body}</p>
            </li>
          );
        })}
      </ul>
      <div className="page-num-container">
        <button
          className={`page-change-btn ${currPageNo === 1 ? "disabled" : ""}  `}
          disabled={currPageNo === 1}
          onClick={previousPage}
        >
          Previous
        </button>
        <ul className="page-num-container list-style-none">
          {pageNumberGroup.map((value, index) => {
            return (
              <li
                className={`page-number ${
                  currPageNo === value ? "active" : ""
                } `}
                key={index}
                onClick={() => changePageTo(value)}
              >
                {value}
              </li>
            );
          })}
        </ul>
        <button
          disabled={currPageNo === Math.floor(posts.length / pageDataLimit)}
          className={`page-change-btn ${
            currPageNo === Math.floor(posts.length / pageDataLimit)
              ? "disabled"
              : ""
          }  `}
          onClick={nextPage}
        >
          Next
        </button>
      </div>
    </div>

进入全屏模式 退出全屏模式

我们首先显示所有帖子,下面是页码和按钮。当我们在第一页时,上一个按钮将被禁用,同样,当我们在最后一页时,下一个按钮将被禁用。

以下是分页组件的样式。将代码写入App.css文件并导入Pagination.js文件。

.heading {
  text-align: center;
  margin: 1rem;
}

.posts-container {
  display: grid;
  grid-template-columns: 18rem 18rem 18rem;
  gap: 1rem;
  align-items: stretch;
  justify-content: center;
}

.post {
  max-width: 16rem;
  text-align: center;
  padding: 1rem;
  margin: 0.5rem;
  color: "#c4c4c4";
  border: 1px solid purple;
  border-radius: 0.25rem;
}

.page-num-container {
  display: flex;
  align-items: center;
  justify-content: center;
}

.page-change-btn {
  padding: 0.5rem 1rem;
  margin: 0 0.5rem;
  border: none;
  border-radius: 0.25rem;
  outline: none;
  background-color: purple;
  color: white;
  cursor: pointer;
}

.disabled {
  cursor: not-allowed;
  background-color: gray;
}

.page-number {
  border: 1px solid grey;
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  line-height: 2rem;
  text-align: center;
  margin: 0 0.25rem;
  cursor: pointer;
}

.active {
  border-color: purple;
}

.list-style-none {
  list-style: none;
  padding-inline-start: 0;
}

进入全屏模式 退出全屏模式

4\。将整个代码放在一起

我们已经准备好分页组件,现在我们只需要在App.js文件中调用该组件。

 <div className="App">
    <Pagination pageDataLimit={5} posts={posts} />
 </div>

进入全屏模式 退出全屏模式

编写完所有代码后,运行

npm start

进入全屏模式 退出全屏模式

整个代码和演示上传到github。

快乐编码!

Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐