首页 > 解决方案 > 如何在反应中使用分页,以便对来自 api 的数据进行相应的分页

问题描述

**As the following code only gives the pagination bar**
 `<Pagination
     activePage={this.state.activePage}
     itemsCountPerPage={2}
     totalItemsCount={data.length}
     pageRangeDisplayed={data.length/3}
     onChange={(e) => this.handleClick(e)} 
   />`

但我想绑定来自 API 的数据

标签: reactjs

解决方案


我为商业项目建造的,它看起来很大。它与 fetch 结合在一起。它使用 Bootstrap 类并且看起来不错(恕我直言) 在此处输入图像描述

export default class Pagination extends React.Component {

  constructor(props) {

    super(props);
    this.state = {
      controlsCount: 5,
      pageSize: 10,
      pageNumber: 0,
      apiUrl: props.apiUrl,
      isHistory: false,
    };
    this.onFetchCallback = props.onFetchCallback;
  }

  setDefaultValues = () => {
    this.setState({
      controlsCount: 5,
      pageSize: 10,
      pageNumber: 0,
      apiUrl: this.props.apiUrl,
      isHistory: true
    });


    let pageNumber = UrlHandler.getParam('pageNumber') || this.state.pageNumber;
    let pageSize = UrlHandler.getParam('pageSize') || this.state.pageSize;

    this.fetchPage(null, pageNumber, pageSize, true);
  };

  /**
   * props:
   *   apiUrl getter
   *   changeState setter
   */

  static range(from, to) {
    let res = [];
    for (let i = from; i <= to; i++) {
      res.push(i);
    }
    return res;
  }

  componentDidMount = () => {
    let pageNumber, pageSize;
    pageNumber = UrlHandler.getParam('pageNumber') || this.state.pageNumber;
    pageSize = UrlHandler.getParam('pageSize') || this.state.pageSize;

    this.fetchPage(null, pageNumber, pageSize);

    $(window).on(EVENT_ON_HISTORY_CHANGE, this.setDefaultValues)
  };



  fetchPage = (e = null, pageNumber, pageSize) => {
    !!e && e.preventDefault();
    Spinner.show();
    fetch(this.state.apiUrl + `page?pageNumber=${pageNumber}&pageSize=${pageSize}`)
      .then(res => res.json())
      .then((respBody) => {
        Spinner.hide();
        this.updatePaginator(respBody);
        this.onFetchCallback({data: respBody.content});
      });
  };

  updatePaginator = (response) => {

    let updateHistory = !this.state.isHistory;


    this.setState({
        pageNumber: response.number,
        totalPages: response.totalPages,
        pageSize: response.size,
        isHistory: false,
      },
      () => {
        UrlHandler.setParams({
          pageNumber: this.state.pageNumber,
          pageSize: this.state.pageSize
        }, updateHistory);
      });

  };


  createPageBtnFirst = () =>
    <PageBtn
      pageNumber={0}
      content="First"
      isDisabled={this.state.pageNumber === 0}
      fetchPage={this.fetchPage}
    />


  createPageBtnLast = () =>
    <PageBtn
      pageNumber={this.state.totalPages - 1}
      content="Last"
      isDisabled={this.state.pageNumber === this.state.totalPages - 1}
      fetchPage={this.fetchPage}
    />

  createPageBtns() {
    let from, to;
    if (this.state.pageNumber === null || this.state.pageNumber === undefined) {
      return;
    }
    if (this.state.pageNumber < this.state.controlsCount / 2) {
      from = 0;
      to = this.state.controlsCount - 1;
    } else {
      from = Math.floor(this.state.pageNumber - this.state.controlsCount / 2 + 1);
      to = Math.floor(this.state.pageNumber + this.state.controlsCount / 2);
    }
    to = to >= this.state.totalPages ? this.state.totalPages - 1 : to;

    return (
      Pagination.range(from, to).map(i =>
        <PageBtn
          pageNumber={i}
          content={i + 1}
          isActive={i === this.state.pageNumber}
          fetchPage={this.fetchPage}
        />
      )
    )
  }

  render() {
    return (
      <div className="card-footer d-flex flex-row d-flex justify-content-between">

        <PaginationSizes pageSize={this.state.pageSize} fetchPage={this.fetchPage}/>

        <nav aria-label="Page navigation " className="text-right">
          <ul className="pagination justify-content-center">
            {this.createPageBtnFirst()}
            {this.createPageBtns()}
            {this.createPageBtnLast()}
          </ul>
        </nav>
      </div>
    );
  }
}


const PageBtn = ({pageNumber, fetchPage, isDisabled, isActive, content}) => (
  <li className={`
          ${isActive ? "page-item active" : "page-item"}
          ${isDisabled ? 'disabled' : ''}`}>
    <a className="page-link hoverable" onClick={(e) => fetchPage(e, pageNumber, UrlHandler.getParam('pageSize'))}>
      {content}
    </a>
  </li>)


export class PaginationSizes extends React.Component {
  state = {
    pageSizes: [5, 10, 20]
  }

  render() {
    return (
      <div className="dropdown ">
        Show: <button className="btn dropdown-toggle bg-white border" type="button" id="dropdownMenuButton"
                      data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">

        {this.props.pageSize ? this.props.pageSize : 'All'}
      </button>
        <div className="dropdown-menu" aria-labelledby="dropdownMenuButton">
          <a className="dropdown-item"
             onClick={(event) => this.props.fetchPage(event, 0, 1000)}>All</a>
          {this.state.pageSizes.map(e =>
            <a className="dropdown-item"
               onClick={(event) => this.props.fetchPage(event, 0, e)}>{e}</a>
          )}

        </div>
      </div>
    )
  }
}

和 util lib 中的 URLhandler

const UrlHandler = (function () {


  let handler = {

    state: {},

    setParamsFromBar: function () {
      UrlHandler.state = new URLSearchParams(location.search);
      $(window).trigger(EVENT_ON_HISTORY_CHANGE);
    },

    getParam: function (param) {
      return this.state.get(param);
    },

    getAllParams: function () {
      return this.state.toString();
    },

    setParams: function (newParams, updateHistory) {
      for ( let [param, value] of Object.entries(newParams)){
        this.state.set(param, value);
      }

      updateHistory && this.updateHistory();
    },

    updateHistory:function () {
      const params = {};

      for(let [param, value] of this.state.entries()){
        params[param] = value;
      }

      history.pushState(
        params,
        'page titile',
        '?' + this.getAllParams()
      )
    }

  };

  $(window).on('popstate', handler.setParamsFromBar);
  handler.state = new URLSearchParams(location.search);

  return handler
})();

更新,因为我看到我的答案不符合您的问题,因为您正在询问某个库。但是尽管如此,我还是搜索了这样的库,但还是决定自己写一个简单的组件


推荐阅读