首页 > 解决方案 > Datatables.net:使用 React Redux 更正服务器端分页

问题描述

我有一个使用 redux 向 API 发出请求的反应组件。此请求执行服务器端分页。

问题是我不明白如何使用 redux 在 datatables.net 中执行此分页。

我确实知道如何在没有数据表的情况下执行分页(实际上,我的组件正在执行它)并且数据表具有ajax 支持,如react-redux-datatable包。两者都通过 ajax 执行对 API 的直接调用,这不是使用 redux 的情况。

import React, { useEffect, useState, useCallback } from 'react'
import { bindActionCreators } from 'redux'

//...

const [skip, setSkip] = useState(10)
const [page, setPage] = useState(0)

// offset = 0 to page 0, offset 10 to page 1, offset 20 to page 2 and so on
<button onClick={() => props.doList({ offset: page * skip  })}>Request</button>

// Table shows the current 10 entries, from a max that is also 10.
<Table data={props.list} columns={predefinedColums}>

//...

// results are acessed by props.list
const mapStateToProps = (state) => {
    return ({
        list: state.reducer.list,
    })
}

const mapDispatchToProps = dispatch =>
    bindActionCreators(
        {
            doList,
        },
        dispatch
    )

目前,我可以显示所需的结果,但不知道如何在数据表组件中对页面更改执行新调用。分页 API 正在工作,所以如果我手动更改页码,它会返回正确的条目。


//Table component

import React, { useEffect } from 'react'
import $ from 'jquery'
import 'datatables.net'
import 'datatables.net-responsive'
import 'datatables.net-select'

// other imports

function Table(props) {
    const { columns, data, title } = props

    useEffect(() => {
        $('#table_id').DataTable().destroy()
        $('#table_id').DataTable({
            retrieve: true,
            data,
            columns,
            "responsive": true,
            "lengthMenu": [
                [10, 25, 50, -1],
                [10, 25, 50, "All"]
            ],
            "language": {
                "emptyTable": i18n.t('emptyDataSourceMessage'),
                "paginate": {
                    "previous": i18n.t('Previous'),
                    "next": i18n.t('Next'),
                    "first": i18n.t("First"),
                    "last": i18n.t("Last"),
                },
                "infoFiltered": i18n.t("(filtered from _MAX_ total entries)"),
                "search": i18n.t('Search'),
                "info": i18n.t("Showing _START_ to _END_ of _TOTAL_ entries"),
                "infoEmpty": i18n.t("Showing 0 to 0 of 0 entries"),
            },
        })
    }, [columns, data])

    return (
        <div className="row">
            <div className="col s12">
                <div class="section section-data-tables">
                    <div className="card">
                        <div className="card-content">
                            <h4 className="card-title">{title}</h4>
                            <div className="row">
                                <div className="col s12">
                                    <table id="table_id" className="display">
                                        <thead>
                                            <tr>
                                                {columns.map((column, key) => <th key={key} data-field={column.field}>{column.title}</th>)}
                                            </tr>
                                        </thead>
                                        <tbody>
                                        </tbody>
                                        <tfoot>
                                            <tr>
                                                {columns.map((column, key) => <th key={key} data-field={column.field}>{column.title}</th>)}
                                            </tr>
                                        </tfoot>
                                    </table>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

export default Table

该表看起来像:(显示 10 个结果的 10 个和唯一的页面)

在此处输入图像描述

我想知道如何使用 redux 正确执行服务器端分页。当前可以知道条目的数量以及要显示的当前页面。

标签: reactjsreduxdatatablespagination

解决方案


只需切出您想要返回给客户端的部分结果(请参阅下面的第一个代码部分)。此外,我在进行服务器端分页时所做的是使用唯一 id 缓存请求的结果。这几乎是强制性的,以防止每次用户切换页码或页面大小时多次重新计算搜索。

我要求一些结果如下:

  1. 客户端:发送搜索(也可以是类别 id)请求。

  2. 服务器:将搜索转换为唯一 ID。查看结果是否已经在缓存中。如果否,则计算搜索,放入缓存中,键为唯一 ID。在搜索结果上使用常见的数组操作(切片),我只取所需的部分。

ret.productIDs =ret.productIDs.slice(imports.config.pageSizes[req.body.pageSize]*(req.body.pageNum), imports.config.pageSizes[req.body.pageSize]*(req.body.pageNum+1));
  1. 服务器:将其与搜索唯一 ID 一起返回(以便下次它可以直接使用此 ID 而不是搜索)。

  2. 客户端:显示搜索结果。每当用户更改页面大小或页面编号时,发送此请求:

    {
        searchId, pageNum, pageSizeIndex
    }
    

现在您还可以使用sortingIndex 将其扩展到排序。另外,在服务器上,您可以记录缓存中搜索结果的可用排序。如果用户要求的排序尚未计算,只需对可用排序之一(已计算排序)进行排序,并将其添加到缓存条目的可用排序中(对于此搜索结果)。所以最终的请求实际上看起来像:

{
    searchId, pageNum, pageSizeIndex, sortingIndex
}

推荐阅读