简体   繁体   English

可重用的 React 分页组件

[英]Reusable React Pagination Component

I am trying to create dynamic pagination react component with reactstrap as UI library.我正在尝试使用reactstrap作为 UI 库创建动态分页反应组件。 I am stuck around the problem of completing the same.我被困在完成相同的问题上。

UsersCard.js用户卡.js

import React, { Component } from 'react'
import axios from 'axios';
import PaginationTable from './PaginationTable';



    export default class UsersCard extends Component {

        constructor(props) {
          super(props)

          this.state = {
              usersData: [],
              loading: false,
              per_page: 3,
              current_page: 1,
              total_data: '',
              currentPosts: []
          }
        }

    async componentDidMount(){
      await axios.get('https://reqres.in/api/users')
        .then(res => {
            this.setState({
              usersData: res.data.data,
              loading: false,
              total_data: res.data.data.length
            })
        })
        .catch(err => console.log(err));

        const indexOfLastPost = this.state.current_page * this.state.per_page;
        const indexOfFirstPage = indexOfLastPost - this.state.per_page;

        const currentPosts = this.state.usersData.slice(indexOfFirstPage, indexOfLastPost);

        this.setState({ currentPosts })

    }

    handleClick = (number) => {
      this.setState({
        current_page: number
      })
    }

      render() {
        const { per_page, handleClick, total_data, current_page, currentPosts } = this.state;

        return (
          <div>
            <table>
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>First Name</th>
                        <th>email</th>
                        <th>Last Name</th>
                    </tr>
                </thead>
                {currentPosts.map(x => {
                return(
                        <React.Fragment key={x.id}>
                                <tbody>
                                    <tr>
                                        <td>{x.id}</td>
                                        <td>{x.first_name}</td>
                                        <td>{x.email}</td>
                                        <td>{x.last_name}</td>
                                    </tr>
                                </tbody>
                        </React.Fragment>
                        )
                })}
            </table>
            <PaginationTable
                      per_page={per_page}
                      current_page={current_page}
                      total_data={total_data}
                      handleClick={handleClick}
                    />
          </div>
        )
      }
    }

PaginationTable.js分页表.js

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

const PaginationTable = ({ per_page, total_data, handleClick, current_page }) => {

    let pageNumbers = [];

    for(let i=1; i<= Math.ceil(total_data/per_page); i++)
    {   
        pageNumbers.push(
        <PaginationItem key={i} active={current_page === i ? true : false}>
            <PaginationLink onClick={() => handleClick(i)} href="#">
                {i}
            </PaginationLink>
        </PaginationItem>)
    }



    return(
            <Pagination aria-label="Page navigation example">
                <PaginationItem disabled={current_page <= 1}>
                    <PaginationLink onClick={()=>handleClick(current_page-1)}
                            previous 
                            href="#" 
                    />
                    </PaginationItem>

                        {pageNumbers}

                <PaginationItem disabled={current_page >= per_page - 1}>
                    <PaginationLink onClick={()=>handleClick(current_page + 1)}
                            next 
                            href="#" 
                    />
                </PaginationItem>
            </Pagination>

    )

} }

export default PaginationTable;导出默认分页表;

My problems go like:我的问题 go 像:

1) Reactstrap pagination UI is not showing properly. 1) Reactstrap 分页 UI 没有正确显示。

2) Whenever I click on the next button, it consoles the error: TypeError: handleClick is not a function . 2)每当我单击next按钮时,它都会显示错误: TypeError: handleClick is not a function

I am bit new to the dynamic pagination concept and am unable to identify the bug I am stuck with.我对动态分页概念有点陌生,无法识别我遇到的错误。 Kindlt help to resolve the same. Kindlt帮助解决同样的问题。 Any code improvements are also welcomed.也欢迎任何代码改进。

There are multiple problems with this approach:这种方法存在多个问题:

  1. this.handleClick has to be passed in from the parent. this.handleClick必须从父级传入。

  2. setState function is asynchronous. setState function 是异步的。 So accessing the state right after setting it might not result in the same state you wish.因此,在设置后立即访问 state 可能不会产生您希望的相同 state。 To get around this React gives you a callback function as second argument.为了解决这个问题,React 给你一个回调 function 作为第二个参数。 This is run only after the state is run.这仅在 state 运行后运行。

  3. You are not updating the currentPosts state after change in pagination.更改分页后,您没有更新currentPosts state。 Pagination component is only concerned with changing page numbers, the change in data has to manually handled.分页组件只关心更改页码,数据的更改必须手动处理。 You can handle this with:您可以通过以下方式处理此问题:

  async componentDidMount() {
    await axios
      .get("https://reqres.in/api/users")
      .then(res => {
        this.setState({
          usersData: res.data.data,
          loading: false,
          total_data: res.data.data.length
        }, () => {
          this.formatData();
        });
      })
      .catch(err => console.log(err));
  }

  formatData() {
    const indexOfLastPost = this.state.current_page * this.state.per_page;
    const indexOfFirstPage = indexOfLastPost - this.state.per_page;

    const currentPosts = this.state.usersData.slice(
      indexOfFirstPage,
      indexOfLastPost
    );

    this.setState({ currentPosts });
  }

  handleClick = number => {
    this.setState({
      current_page: number
    }, () => {
      this.formatData();
    });
  };

Updated Stackblitz更新了 Stackblitz

About the first.关于第一个。 You are trying to render just an array of jsx elements in pageNumbers .您正在尝试仅在pageNumbers中呈现一组 jsx 元素。 Instead of that - you could just push numbers into this array:取而代之的是-您可以将数字推入此数组:

let pageNumbers = [];

for(let i=1; i<= Math.ceil(total_data/per_page); i++)
{   
  pageNumbers.push(i)
}

and then render pagination item directly where it should be using map.然后直接在应该使用 map 的地方渲染分页项目。

{pageNumbers.map(i => (
  <PaginationItem key={i} active={current_page === i ? true : false}>
      <PaginationLink onClick={() => handleClick(i)} href="#">
         {i}
      </PaginationLink>
   </PaginationItem>
))}

About the second: handleClick is not a function because you are first defining it above the render function and then you are overriding it when destructuring state, but there is no such thing as handleClick in your state, so it is assigned to null or undefined. About the second: handleClick is not a function because you are first defining it above the render function and then you are overriding it when destructuring state, but there is no such thing as handleClick in your state, so it is assigned to null or undefined. All you have to do is remove it in destructuring assignment and pass it as this.handleClick and it should work.您所要做的就是在解构赋值中删除它并将其作为this.handleClick传递,它应该可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM