使用 json-server 和 React.js 进行分页

Posted

技术标签:

【中文标题】使用 json-server 和 React.js 进行分页【英文标题】:Pagination with json-server and React.js 【发布时间】:2017-12-05 01:16:52 【问题描述】:

我正在尝试对我在 React 中与 JSON 服务器一起使用的 JSON 数据进行分页。我目前正在使用 splice 将数据分解为每页 10 个项目的页面。为了从每个拼接中获取数据,我有一个无序列表,其中为列表项分配了数据。实际上,我只想拥有页面和下一个按钮,而不是在页面顶部列出每个页面,但我似乎无法绕开它。我想使用_page _limit。任何帮助,将不胜感激。这是代码。

import React,  Component  from 'react';
// added axios to assist with API calls.
import axios from 'axios';

import './App.css';
import Card from './Card.js';
import SearchBar from "./SearchBar.js"
import star from './images/star.svg';
import wars from './images/wars.svg';

class App extends Component 

  constructor(props) 
    super(props);
    this.state = 
      people: []
    
  

  componentDidMount() 
    this.getPeopleData();
  

  getPeopleData(search) 
    axios.get('http://localhost:3008/people?_start=0&_end=9&q=' + search).then((response) => 
      this.setState (
        people: response.data
      );
    );
  


  //1. Using axios and decided to use the slice method rather than the _page _limit from https://github.com/typicode/json-server#slice
  limitPerPage (begin, end) 
    axios(`http://localhost:3008/people?_start=$begin&_end=$end`).then((response) => 
      this.setState (
        people: response.data
      );
    );
  
  
  render() 
    return (
      <div className='content'>
        <div className='logo'>
          <img src=star  />
          <span className='interview-text'>The Interview</span>
          <img src=wars  />
        </div>


        <h2>Cards</h2>

        /* Decided to display the card pages as a list. Each page holds 10 cards */
        <ul className="card-pagination">
          <li>
            <a onClick=() => this.limitPerPage(0, 9)>Page 1</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(10, 19)>Page 2</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(20, 29)>Page 3</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(30, 39)>Page 4</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(40, 49)>Page 5</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(50, 59)>Page 6</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(60, 69)>Page 7</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(70, 79)>Page 8</a>
          </li>

          <li>
            <a onClick=() => this.limitPerPage(80, 89)>Page 9</a>
          </li>
        
        </ul>

        this.state.people.map((person) => 
          return <Card
                    key=person.id
                    id=person.id
                    name=person.name
                    imageURL=('http://localhost:3008/' + person.image)
                    birthday=person.birth_year
                    planetList=this.state.planets
                    homeWorld=person.homeworld
                  />
        )
      </div>
    );
  


export default App;

【问题讨论】:

【参考方案1】:
constructor(props) 
  super(props);
  this.state = 
    people: [],
    _page_limit: 10,
    currentPage: 0
  


...

limitPerPage (begin, end, increase) 
  axios(`http://localhost:3008/people?_start=$begin&_end=$end`).then((response) => 
    this.setState (
      people: response.data,
      currentPage: this.state.currentPage + increase
    );
  );


_renderLinks() 
  var cp = this.state.currentPage
  if (cp == 0) 
    // show only "Page 1" and "Next"
    return (
      <ul className="card-pagination">
        <li>Page 1</li>
        <li><a onClick=() => this.limitPerPage(10, 20, 1)>Next</a></li>
      </ul>
    )
   else if (cp < this.state._page_limit - 1) 
    // show "Back", "Page X" and "Next"
    return (
      <ul className="card-pagination">
        <li><a onClick=() => this.limitPerPage((cp-1) * 10, cp * 10), -1>Back</a></li>
        <li>Page (cp + 1</li>
        <li><a onClick=() => this.limitPerPage((cp+1) * 10, (cp+2) * 10, 1>Next</a></li>
      </ul>
    )
   else 
    // show "Back", "Page X" and "Next"
    return (
      <ul className="card-pagination">
        <li><a onClick=() => this.limitPerPage((cp-1) * 10, cp * 10, -1)>Back</a></li>
        <li>Page (cp-1)</li>
      </ul>
    )
  


render() 
    var _page_limit = 10
    return (
      <div className='content'>
        <div className='logo'>
          <img src=star  />
          <span className='interview-text'>The Interview</span>
          <img src=wars  />
        </div>


        <h2>Cards</h2>

        this._renderLinks()

        this.state.people.map((person) => 
          return <Card
            key=person.id
            id=person.id
            name=person.name
            imageURL=('http://localhost:3008/' + person.image)
            birthday=person.birth_year
            planetList=this.state.planets
            homeWorld=person.homeworld
            />
        )
      </div>
    );
  

表达式[...Array(_page_limit).keys()] 是用于创建介于 0 和 (_page_limit - 1) 之间的数字数组的快捷方式。

【讨论】:

这会稍微清理一下代码,但现在每页只显示 9 个项目,并且仍然在顶部显示每个页面,而不是有一个下一步按钮。任何想法为什么将其限制为每页 9 个以及如何让它只列出用户所在的页面链接而不是一次列出所有 10 个页面?编辑:我确实将 +9 更改为 +10 以获得每页 10 个项目。 我刚刚检查了 json server slice link 您在 limitPerPage 函数之前的评论。它说_start is inclusive and _end exclusive。所以我认为将limitPerPage(num * 10, (num * 10) + 9) 更改为limitPerPage(num * 10, (num * 10) + 10) 会将其从每页9 更改为10。 “仅列出用户所在的页面链接” - 你能详细说明一下吗? 我的猜测是,例如您在第 4 页。您只希望 backnext 按钮分别充当第 3 页和第 5 页的点击(不显示链接全部 10 页)。如果您在第 1 页,则仅显示下一个按钮。如果是这种情况,您必须跟踪用户当前所在的页面并相应地呈现链接。 您的猜测完全正确。我将如何跟踪并渲染它? 我部分更新了我的答案以跟踪页面。剩下的最后一部分是在单击新链接时更新this.state.currentPage

以上是关于使用 json-server 和 React.js 进行分页的主要内容,如果未能解决你的问题,请参考以下文章

Json-server 使用 React js 和 Redux 响应错误 404 not found Post Method

json-server的下载和基本使用

如何动态启动 json-server

json-server 0.8.12 和 Express 4.x 路由

如何使用 useForm 钩子获取输入值,然后使用 json-server 执行 POST?

如何在 json-server 上添加标头?