如何在React中实现分页

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

我是 ReactJS 新手,正在其中创建一个简单的 TODO 应用程序。实际上,这是一个非常基本的应用程序,没有数据库连接,任务存储在数组中。我添加了编辑和删除功能,现在我想添加分页。

如何实施?任何帮助将不胜感激。谢谢...!!

reactjs pagination
12个回答
175
投票

我最近在纯 React JS 中实现了分页。这是一个工作演示:http://codepen.io/PiotrBerebecki/pen/pEYPbY

您当然必须调整逻辑和页码显示方式,以满足您的要求。

完整代码:

class TodoApp extends React.Component {
  constructor() {
    super();
    this.state = {
      todos: ['a','b','c','d','e','f','g','h','i','j','k'],
      currentPage: 1,
      todosPerPage: 3
    };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(event) {
    this.setState({
      currentPage: Number(event.target.id)
    });
  }

  render() {
    const { todos, currentPage, todosPerPage } = this.state;

    // Logic for displaying todos
    const indexOfLastTodo = currentPage * todosPerPage;
    const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
    const currentTodos = todos.slice(indexOfFirstTodo, indexOfLastTodo);

    const renderTodos = currentTodos.map((todo, index) => {
      return <li key={index}>{todo}</li>;
    });

    // Logic for displaying page numbers
    const pageNumbers = [];
    for (let i = 1; i <= Math.ceil(todos.length / todosPerPage); i++) {
      pageNumbers.push(i);
    }

    const renderPageNumbers = pageNumbers.map(number => {
      return (
        <li
          key={number}
          id={number}
          onClick={this.handleClick}
        >
          {number}
        </li>
      );
    });

    return (
      <div>
        <ul>
          {renderTodos}
        </ul>
        <ul id="page-numbers">
          {renderPageNumbers}
        </ul>
      </div>
    );
  }
}


ReactDOM.render(
  <TodoApp />,
  document.getElementById('app')
);

15
投票

我尝试重新创建 piotr-berebecki 给出的简单分页示例,这非常棒。但是当页面很多时,分页就会在屏幕上溢出。因此,我使用上一个和后退按钮以及前进和后退按钮在页面之间来回传输。对于设计部分,我使用了 Bootstrap 3。

您可以使用页面绑定值自定义分页中显示的页面数。确保对 upperPageBound 和 pageBound 使用相同的值。

    class TodoApp extends React.Component {
          constructor() {
            super();
            this.state = {
              todos: ['a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z'],
              currentPage: 1,
              todosPerPage: 3,
              upperPageBound: 3,
              lowerPageBound: 0,
              isPrevBtnActive: 'disabled',
              isNextBtnActive: '',
              pageBound: 3
            };
            this.handleClick = this.handleClick.bind(this);
            this.btnDecrementClick = this.btnDecrementClick.bind(this);
            this.btnIncrementClick = this.btnIncrementClick.bind(this);
            this.btnNextClick = this.btnNextClick.bind(this);
            this.btnPrevClick = this.btnPrevClick.bind(this);
            // this.componentDidMount = this.componentDidMount.bind(this);
            this.setPrevAndNextBtnClass = this.setPrevAndNextBtnClass.bind(this);
          }
          componentDidUpdate() {
                $("ul li.active").removeClass('active');
                $('ul li#'+this.state.currentPage).addClass('active');
          }
          handleClick(event) {
            let listid = Number(event.target.id);
            this.setState({
              currentPage: listid
            });
            $("ul li.active").removeClass('active');
            $('ul li#'+listid).addClass('active');
            this.setPrevAndNextBtnClass(listid);
          }
          setPrevAndNextBtnClass(listid) {
            let totalPage = Math.ceil(this.state.todos.length / this.state.todosPerPage);
            this.setState({isNextBtnActive: 'disabled'});
            this.setState({isPrevBtnActive: 'disabled'});
            if(totalPage === listid && totalPage > 1){
                this.setState({isPrevBtnActive: ''});
            }
            else if(listid === 1 && totalPage > 1){
                this.setState({isNextBtnActive: ''});
            }
            else if(totalPage > 1){
                this.setState({isNextBtnActive: ''});
                this.setState({isPrevBtnActive: ''});
            }
        }
          btnIncrementClick() {
              this.setState({upperPageBound: this.state.upperPageBound + this.state.pageBound});
              this.setState({lowerPageBound: this.state.lowerPageBound + this.state.pageBound});
              let listid = this.state.upperPageBound + 1;
              this.setState({ currentPage: listid});
              this.setPrevAndNextBtnClass(listid);
        }
          btnDecrementClick() {
            this.setState({upperPageBound: this.state.upperPageBound - this.state.pageBound});
            this.setState({lowerPageBound: this.state.lowerPageBound - this.state.pageBound});
            let listid = this.state.upperPageBound - this.state.pageBound;
            this.setState({ currentPage: listid});
            this.setPrevAndNextBtnClass(listid);
        }
        btnPrevClick() {
            if((this.state.currentPage -1)%this.state.pageBound === 0 ){
                this.setState({upperPageBound: this.state.upperPageBound - this.state.pageBound});
                this.setState({lowerPageBound: this.state.lowerPageBound - this.state.pageBound});
            }
            let listid = this.state.currentPage - 1;
            this.setState({ currentPage : listid});
            this.setPrevAndNextBtnClass(listid);
        }
        btnNextClick() {
            if((this.state.currentPage +1) > this.state.upperPageBound ){
                this.setState({upperPageBound: this.state.upperPageBound + this.state.pageBound});
                this.setState({lowerPageBound: this.state.lowerPageBound + this.state.pageBound});
            }
            let listid = this.state.currentPage + 1;
            this.setState({ currentPage : listid});
            this.setPrevAndNextBtnClass(listid);
        }
          render() {
            const { todos, currentPage, todosPerPage,upperPageBound,lowerPageBound,isPrevBtnActive,isNextBtnActive } = this.state;
            // Logic for displaying current todos
            const indexOfLastTodo = currentPage * todosPerPage;
            const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
            const currentTodos = todos.slice(indexOfFirstTodo, indexOfLastTodo);

            const renderTodos = currentTodos.map((todo, index) => {
              return <li key={index}>{todo}</li>;
            });

            // Logic for displaying page numbers
            const pageNumbers = [];
            for (let i = 1; i <= Math.ceil(todos.length / todosPerPage); i++) {
              pageNumbers.push(i);
            }

            const renderPageNumbers = pageNumbers.map(number => {
                if(number === 1 && currentPage === 1){
                    return(
                        <li key={number} className='active' id={number}><a href='#' id={number} onClick={this.handleClick}>{number}</a></li>
                    )
                }
                else if((number < upperPageBound + 1) && number > lowerPageBound){
                    return(
                        <li key={number} id={number}><a href='#' id={number} onClick={this.handleClick}>{number}</a></li>
                    )
                }
            });
            let pageIncrementBtn = null;
            if(pageNumbers.length > upperPageBound){
                pageIncrementBtn = <li className=''><a href='#' onClick={this.btnIncrementClick}> &hellip; </a></li>
            }
            let pageDecrementBtn = null;
            if(lowerPageBound >= 1){
                pageDecrementBtn = <li className=''><a href='#' onClick={this.btnDecrementClick}> &hellip; </a></li>
            }
            let renderPrevBtn = null;
            if(isPrevBtnActive === 'disabled') {
                renderPrevBtn = <li className={isPrevBtnActive}><span id="btnPrev"> Prev </span></li>
            }
            else{
                renderPrevBtn = <li className={isPrevBtnActive}><a href='#' id="btnPrev" onClick={this.btnPrevClick}> Prev </a></li>
            }
            let renderNextBtn = null;
            if(isNextBtnActive === 'disabled') {
                renderNextBtn = <li className={isNextBtnActive}><span id="btnNext"> Next </span></li>
            }
            else{
                renderNextBtn = <li className={isNextBtnActive}><a href='#' id="btnNext" onClick={this.btnNextClick}> Next </a></li>
            }
            return (
              <div>
                  <ul>
                  {renderTodos}
                </ul>
                <ul id="page-numbers" className="pagination">
                  {renderPrevBtn}
                  {pageDecrementBtn}
                  {renderPageNumbers}
                  {pageIncrementBtn}
                  {renderNextBtn}
                </ul>
              </div>
            );
          }
        }


        ReactDOM.render(
          <TodoApp />,
          document.getElementById('app')
        );

工作演示链接:https://codepen.io/mhmanandhar/pen/oEWBqx

图片:simple react pagination


6
投票

这是一种从react-bootstrap lib创建自定义分页组件的方法,您可以在整个项目中使用该组件

您的分页组件(pagination.jsx 或 js)

import React, { Component } from "react"; 
import { Pagination } from "react-bootstrap"; 
import PropTypes from "prop-types";

export default class PaginationHandler extends Component {  

   constructor(props) {
    super(props);
    this.state = {
      paging: {
        offset: 0,
        limit: 10
      },
      active: 0
    };  
    }

  pagingHandler = () => {
    let offset = parseInt(event.target.id);
    this.setState({
      active: offset
    });
    this.props.pageHandler(event.target.id - 1);   };

  nextHandler = () => {
    let active = this.state.active;
    this.setState({
      active: active + 1
    });
    this.props.pageHandler(active + 1);   };

  backHandler = () => {
    let active = this.state.active;
    this.setState({
      active: active - 1
    });
    this.props.pageHandler(active - 1);   };

  renderPageNumbers = (pageNumbers, totalPages) => {
    let { active } = this.state;
    return (
      <Pagination>
        <Pagination.Prev disabled={active < 5} onClick={ active >5 && this.backHandler} />

        {
      pageNumbers.map(number => {
              if (
                number >= parseInt(active) - 3 &&
                number <= parseInt(active) + 3 
              ) {
                return (
                  <Pagination.Item
                    id={number}
                    active={number == active}
                    onClick={this.pagingHandler}
                  >
                    {number}
                  </Pagination.Item>
                );
              } else {
                return null;
              }
        })}
        <Pagination.Next onClick={ active <= totalPages -4 && this.nextHandler} />
      </Pagination>
    );   };

  buildComponent = (props, state) => {
    const { totalPages } = props;
    const pageNumbers = [];
    for (let i = 1; i <= totalPages; i++) {
      pageNumbers.push(i);
    }
    return (
      <div className="pull-right">
      {this.renderPageNumbers(pageNumbers ,totalPages)}
      </div>
    );   
};

  render() {
    return this.buildComponent(this.props, this.state);
  } 

} 
   PaginationHandler.propTypes = 
   {
    paging: PropTypes.object,
    pageHandler: PropTypes.func,
    totalPages: PropTypes.object 
   };

在父组件中使用上述子组件,如下所示

import Pagination from "../pagination";

pageHandler = (offset) =>{
      this.setState(({ paging }) => ({
        paging: { ...paging, offset: offset }
      }));
   }
   render() {
    return (
      <div>
         <Pagination
          paging = {paging}
          pageHandler = {this.pageHandler}
          totalPages = {totalPages}>
          </Pagination>
      </div>
    );
  }
     

4
投票

示例分页 React js 工作代码

import React, { Component } from 'react';
import {
Pagination,
PaginationItem,
PaginationLink
} from "reactstrap";


let prev  = 0;
let next  = 0;
let last  = 0;
let first = 0;
export default class SamplePagination extends Component {
   constructor() {
     super();
     this.state = {
       todos: ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','T','v','u','w','x','y','z'],
       currentPage: 1,
       todosPerPage: 3,

     };
     this.handleClick = this.handleClick.bind(this);
     this.handleLastClick = this.handleLastClick.bind(this);
     this.handleFirstClick = this.handleFirstClick.bind(this);
   }

   handleClick(event) {
     event.preventDefault();
     this.setState({
       currentPage: Number(event.target.id)
     });
   }

   handleLastClick(event) {
     event.preventDefault();
     this.setState({
       currentPage:last
     });
   }
   handleFirstClick(event) {
     event.preventDefault();
     this.setState({
       currentPage:1
     });
   }
   render() {
     let { todos, currentPage, todosPerPage } = this.state;

     // Logic for displaying current todos
     let indexOfLastTodo = currentPage * todosPerPage;
     let indexOfFirstTodo = indexOfLastTodo - todosPerPage;
     let currentTodos = todos.slice(indexOfFirstTodo, indexOfLastTodo);
      prev  = currentPage > 0 ? (currentPage -1) :0;
      last = Math.ceil(todos.length/todosPerPage);
      next  = (last === currentPage) ?currentPage: currentPage +1;

     // Logic for displaying page numbers
     let pageNumbers = [];
     for (let i = 1; i <=last; i++) {
       pageNumbers.push(i);
     }

      return (
       <div>
         <ul>
          {
            currentTodos.map((todo,index) =>{
              return <li key={index}>{todo}</li>;
            })
          }
         </ul><ul id="page-numbers">
         <nav>
          <Pagination>
          <PaginationItem>
          { prev === 0 ? <PaginationLink disabled>First</PaginationLink> :
              <PaginationLink onClick={this.handleFirstClick} id={prev} href={prev}>First</PaginationLink>
          }
          </PaginationItem>
          <PaginationItem>
          { prev === 0 ? <PaginationLink disabled>Prev</PaginationLink> :
              <PaginationLink onClick={this.handleClick} id={prev} href={prev}>Prev</PaginationLink>
          }
          </PaginationItem>
             {
              pageNumbers.map((number,i) =>
              <Pagination key= {i}>
              <PaginationItem active = {pageNumbers[currentPage-1] === (number) ? true : false} >
               <PaginationLink onClick={this.handleClick} href={number} key={number} id={number}>
               {number}
               </PaginationLink>
               </PaginationItem>
              </Pagination>
            )}

         <PaginationItem>
         {
           currentPage === last ? <PaginationLink disabled>Next</PaginationLink> :
           <PaginationLink onClick={this.handleClick} id={pageNumbers[currentPage]} href={pageNumbers[currentPage]}>Next</PaginationLink>
         }
         </PaginationItem>

         <PaginationItem>
         {
           currentPage === last ? <PaginationLink disabled>Last</PaginationLink> :
           <PaginationLink onClick={this.handleLastClick} id={pageNumbers[currentPage]} href={pageNumbers[currentPage]}>Last</PaginationLink>
         }
         </PaginationItem>
         </Pagination>
          </nav>
         </ul>
       </div>
     );
   }
 }

 ReactDOM.render(
  <SamplePagination />,
  document.getElementById('root')
);

3
投票

我最近创建了这个分页组件,它实现了像 Google 搜索结果一样的分页逻辑:

import React, { PropTypes } from 'react';
 
const propTypes = {
    items: PropTypes.array.isRequired,
    onChangePage: PropTypes.func.isRequired,
    initialPage: PropTypes.number   
}
 
const defaultProps = {
    initialPage: 1
}
 
class Pagination extends React.Component {
    constructor(props) {
        super(props);
        this.state = { pager: {} };
    }
 
    componentWillMount() {
        this.setPage(this.props.initialPage);
    }
 
    setPage(page) {
        var items = this.props.items;
        var pager = this.state.pager;
 
        if (page < 1 || page > pager.totalPages) {
            return;
        }
 
        // get new pager object for specified page
        pager = this.getPager(items.length, page);
 
        // get new page of items from items array
        var pageOfItems = items.slice(pager.startIndex, pager.endIndex + 1);
 
        // update state
        this.setState({ pager: pager });
 
        // call change page function in parent component
        this.props.onChangePage(pageOfItems);
    }
 
    getPager(totalItems, currentPage, pageSize) {
        // default to first page
        currentPage = currentPage || 1;
 
        // default page size is 10
        pageSize = pageSize || 10;
 
        // calculate total pages
        var totalPages = Math.ceil(totalItems / pageSize);
 
        var startPage, endPage;
        if (totalPages <= 10) {
            // less than 10 total pages so show all
            startPage = 1;
            endPage = totalPages;
        } else {
            // more than 10 total pages so calculate start and end pages
            if (currentPage <= 6) {
                startPage = 1;
                endPage = 10;
            } else if (currentPage + 4 >= totalPages) {
                startPage = totalPages - 9;
                endPage = totalPages;
            } else {
                startPage = currentPage - 5;
                endPage = currentPage + 4;
            }
        }
 
        // calculate start and end item indexes
        var startIndex = (currentPage - 1) * pageSize;
        var endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);
 
        // create an array of pages to ng-repeat in the pager control
        var pages = _.range(startPage, endPage + 1);
 
        // return object with all pager properties required by the view
        return {
            totalItems: totalItems,
            currentPage: currentPage,
            pageSize: pageSize,
            totalPages: totalPages,
            startPage: startPage,
            endPage: endPage,
            startIndex: startIndex,
            endIndex: endIndex,
            pages: pages
        };
    }
 
    render() {
        var pager = this.state.pager;
 
        return (
            <ul className="pagination">
                <li className={pager.currentPage === 1 ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(1)}>First</a>
                </li>
                <li className={pager.currentPage === 1 ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(pager.currentPage - 1)}>Previous</a>
                </li>
                {pager.pages.map((page, index) =>
                    <li key={index} className={pager.currentPage === page ? 'active' : ''}>
                        <a onClick={() => this.setPage(page)}>{page}</a>
                    </li>
                )}
                <li className={pager.currentPage === pager.totalPages ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(pager.currentPage + 1)}>Next</a>
                </li>
                <li className={pager.currentPage === pager.totalPages ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(pager.totalPages)}>Last</a>
                </li>
            </ul>
        );
    }
}
 
Pagination.propTypes = propTypes;
Pagination.defaultProps
export default Pagination;

这是一个示例 App 组件,它使用 Pagination 组件对包含 150 个示例项目的列表进行分页:

import React from 'react';
import Pagination from './Pagination';
 
class App extends React.Component {
    constructor() {
        super();
 
        // an example array of items to be paged
        var exampleItems = _.range(1, 151).map(i => { return { id: i, name: 'Item ' + i }; });
 
        this.state = {
            exampleItems: exampleItems,
            pageOfItems: []
        };
 
        // bind function in constructor instead of render (https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md)
        this.onChangePage = this.onChangePage.bind(this);
    }
 
    onChangePage(pageOfItems) {
        // update state with new page of items
        this.setState({ pageOfItems: pageOfItems });
    }
 
    render() {
        return (
            <div>
                <div className="container">
                    <div className="text-center">
                        <h1>React - Pagination Example with logic like Google</h1>
                        {this.state.pageOfItems.map(item =>
                            <div key={item.id}>{item.name}</div>
                        )}
                        <Pagination items={this.state.exampleItems} onChangePage={this.onChangePage} />
                    </div>
                </div>
                <hr />
                <div className="credits text-center">
                    <p>
                        <a href="http://jasonwatmore.com" target="_top">JasonWatmore.com</a>
                    </p>
                </div>
            </div>
        );
    }
}
 
export default App;

有关更多详细信息和现场演示,您可以查看这篇文章


2
投票

请在codesandbox中查看此代码示例

https://codesandbox.io/s/pagino-13pit

import Pagino from "pagino";
import { useState, useMemo } from "react";

export default function App() {
  const [pages, setPages] = useState([]);

  const pagino = useMemo(() => {
    const _ = new Pagino({
      showFirst: false,
      showLast: false,
      onChange: (page, count) => setPages(_.getPages())
    });

    _.setCount(10);

    return _;
  }, []);

  const hanglePaginoNavigation = (type) => {
    if (typeof type === "string") {
      pagino[type]?.();
      return;
    }

    pagino.setPage(type);
  };

  return (
    <div>
      <h1>Page: {pagino.page}</h1>
      <ul>
        {pages.map((page) => (
          <button key={page} onClick={() => hanglePaginoNavigation(page)}>
            {page}
          </button>
        ))}
      </ul>
    </div>
  );
}

2
投票

1- 使用

react-bootstrap

import React from "react";
import { Pagination } from "react-bootstrap";
import Link from "next/link";

interface PaginateProps {
  pages: number;
  page: number;
  keyword?: string;
  isAdmin?: boolean;
}

const Paginate = ({
  pages,
  page,
  // keyword is for searching
  keyword = "",
  isAdmin = false,
}: PaginateProps) => {
  return pages > 1 ? (
    <Pagination>
      {/* keys returns a new Array iterator contians the keys for each index */} 
      // pages is total number of pages
      {[...Array(pages).keys()].map((x) => (
        // this is next.js component. you could use react Link
        <Link
          passHref
          key={x + 1}
          href={
            !isAdmin
              // since array indexing starts at 0, use x+1
              ? `/?keyword=${keyword}&page=${x + 1}`
              : `/admin/productlist/?keyword=${keyword}&page=${x + 1}`
          }
        >
          <Pagination.Item active={x + 1 === page}>{x + 1}</Pagination.Item>
        </Link>
      ))}
    </Pagination>
  ) : null;
};

export default Paginate;

然后在页面中使用它。

    <Paginate page={page} pages={pages} keyword={keyword} />

2-使用react-js分页

  import Pagination from "react-js-pagination";

  // bootstrap class to center 
  <div className="d-flex justify-content-center mt-5">
      <Pagination
        activePage={page}
        itemsCountPerPage={resPerPageValue}
        totalItemsCount={Count}
        onChange={handlePagination}
        nextPageText={"Next"}
        prevPageText={"Prev"}
        firstPageText={"First"}
        lastPageText={"Last"}
        // overwriting the style
        itemClass="page-item"
        linkClass="page-link"
      />
    </div>

onChange 处理程序

 const handlePagination = (pageNumber) => {
    // window.location.href will reload entire page
    router.push(`/?page=${pageNumber}`);
  };

1
投票

我已经在ReactJs中实现了分页+搜索,请参阅输出: Pagination in React

在 GitHub 上查看完整代码:https://github.com/navanathjadhav/generic-pagination

还可以访问这篇文章来逐步实现分页:https://everblogs.com/react/3-simple-steps-to-add-pagination-in-react/


0
投票

我最近创建了一个库,它有助于处理分页情况,例如:

  • 在 Redux 中存储标准化数据
  • 基于搜索过滤器缓存页面
  • 简化的反应虚拟化列表用法
  • 后台刷新结果
  • 存储上次访问的页面和使用的过滤器

DEMO页面实现了以上所有功能。

您可以在Github

上找到源代码

0
投票

一个用于渲染分页的 ReactJS 哑组件。您还可以使用这个库:

https://www.npmjs.com/package/react-js-pagination

一些示例如下:

http://vayser.github.io/react-js-pagination/

您也可以使用这个https://codepen.io/PiotrBerebecki/pen/pEYPbY


0
投票

确保将其作为一个单独的组件 我用过tabler-react

import * as React from "react";
import { Page,  Button } from "tabler-react";
class PaginateComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
            limit: 5, // optional
            page: 1
        };
    }

paginateValue = (page) => {
    this.setState({ page: page });
    console.log(page) // access this value from parent component 
}

paginatePrevValue = (page) => {
    this.setState({ page: page });
    console.log(page)  // access this value from parent component
}
paginateNxtValue = (page) => {
       this.setState({ page: page });
       console.log(page)  // access this value from parent component
    }

    render() {
        return (
            <div>    
                <div>
                    <Button.List>
                        <Button
                      disabled={this.state.page === 0}
                      onClick={() => this.paginatePrevValue(this.state.page - 1)}
                            outline
                            color="primary"
                        >
                            Previous
                      </Button>

                        {this.state.array.map((value, index) => {
                            return (
                                <Button
                                    onClick={() => this.paginateValue(value)}
                                    color={
                                        this.state.page === value
                                            ? "primary"
                                            : "secondary"
                                    }
                                >
                                    {value}
                                </Button>
                            );
                        })}

                        <Button
                            onClick={() => this.paginateNxtValue(this.state.page + 1)}
                            outline
                            color="secondary"
                        >
                            Next
                      </Button>
                    </Button.List>
                </div>
            </div>

        )
    }
}

export default PaginateComponent;

-5
投票

给你一个分页组件,对于新手来说可能有点难以理解

react
:

https://www.npmjs.com/package/pagination

© www.soinside.com 2019 - 2024. All rights reserved.