You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合React Redux实现Datatables.net的服务端分页?

结合React Redux实现Datatables.net服务端分页方案

核心思路是启用Datatables的服务端处理模式,让Datatables的分页操作触发你的Redux Action,而非直接发起AJAX请求。同时同步Redux中存储的总条目数、当前页数据到Datatables,确保分页控件能正确渲染。下面是具体实现步骤:


步骤1:调整父组件,传递必要参数给Table组件

首先确保父组件从Redux中获取总条目数,并把数据请求Action、总条目数一起传递给Table组件:

import React from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { doList } from './your-action-file'
import Table from './Table'
import predefinedColums from './your-columns'

const ParentComponent = (props) => {
  return (
    <div>
      {/* 无需手动触发请求,Datatables会自动处理分页请求 */}
      <Table 
        data={props.list} 
        columns={predefinedColums}
        totalCount={props.totalCount}
        fetchData={props.doList}
        title="Your Table Title"
      />
    </div>
  )
}

const mapStateToProps = (state) => {
  return ({
    list: state.reducer.list,
    totalCount: state.reducer.totalCount, // 从Redux中读取总条目数
  })
}

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

export default connect(mapStateToProps, mapDispatchToProps)(ParentComponent)

步骤2:修改Table组件,配置Datatables服务端模式

更新Table组件,开启serverSide: true,并自定义ajax回调触发Redux Action,同时同步数据状态:

import React, { useEffect, useRef } from 'react'
import $ from 'jquery'
import 'datatables.net'
import 'datatables.net-responsive'
import 'datatables.net-select'
import i18n from './your-i18n-config'

function Table(props) {
  const { columns, data, title, totalCount, fetchData } = props
  const tableRef = useRef(null) // 使用Ref替代ID选择器,避免多实例冲突

  useEffect(() => {
    // 销毁已有Datatables实例,避免重复初始化
    if ($.fn.DataTable.isDataTable(tableRef.current)) {
      $(tableRef.current).DataTable().destroy()
    }

    const table = $(tableRef.current).DataTable({
      retrieve: true,
      serverSide: true, // 关键:开启服务端处理
      processing: true, // 显示加载状态提示
      data: data, // 传入当前页数据
      columns: 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"),
      },
      // 自定义AJAX回调,Datatables自动传递分页参数
      ajax: function(dtParams, callback) {
        // dtParams.start = 偏移量(对应你的offset),dtParams.length = 每页条数
        const requestParams = {
          offset: dtParams.start,
          limit: dtParams.length
        }

        // 触发Redux Action获取数据
        fetchData(requestParams)
          .then(() => {
            // 告知Datatables请求结果,确保分页控件正确渲染
            callback({
              draw: dtParams.draw, // 必须返回,用于Datatables跟踪请求顺序
              recordsTotal: totalCount, // 总条目数
              recordsFiltered: totalCount, // 无搜索过滤时与totalCount一致
              data: data // 当前页数据
            })
          })
          .catch(err => {
            // 错误处理:返回空数据避免表格报错
            callback({
              draw: dtParams.draw,
              recordsTotal: 0,
              recordsFiltered: 0,
              data: []
            })
          })
      }
    })

    // 组件卸载时清理Datatables实例
    return () => {
      if ($.fn.DataTable.isDataTable(tableRef.current)) {
        table.destroy()
      }
    }
  }, [columns, data, totalCount, fetchData])

  return (
    <div className="row">
      <div className="col s12">
        <div className="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 ref={tableRef} 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

步骤3:更新Redux Action与Reducer,存储总条目数

确保你的API返回当前页数据和总条目数,并在Action和Reducer中处理这部分数据:

// Action示例
export const doList = (params) => async (dispatch) => {
  try {
    const response = await api.get('/your-api-endpoint', { params })
    // 假设API返回格式:{ data: [...], total: 150 }
    dispatch({
      type: 'FETCH_LIST_SUCCESS',
      payload: {
        list: response.data.data,
        totalCount: response.data.total
      }
    })
  } catch (err) {
    dispatch({ type: 'FETCH_LIST_FAILURE' })
    // 可添加错误提示逻辑
  }
}

// Reducer示例
const initialState = {
  list: [],
  totalCount: 0
}

const reducer = (state = initialState, action) => {
  switch(action.type) {
    case 'FETCH_LIST_SUCCESS':
      return {
        ...state,
        list: action.payload.list,
        totalCount: action.payload.totalCount
      }
    case 'FETCH_LIST_FAILURE':
      return {
        ...state,
        list: []
      }
    default:
      return state
  }
}

export default reducer

关键注意事项

  1. 避免ID选择器:使用React的useRef获取表格元素,避免多表格实例冲突。
  2. 同步状态:必须将Redux中的totalCount传递给Datatables,否则分页控件无法正确计算总页数。
  3. draw参数:必须原样返回Datatables传递的draw参数,否则分页可能出现顺序混乱。
  4. 加载状态:开启processing: true能在请求数据时显示加载动画,提升用户体验。

配置完成后,点击Datatables的分页按钮会自动触发Redux Action获取对应页的数据,表格会自动更新内容,分页控件也会根据总条目数正确显示。

内容的提问来源于stack exchange,提问作者Luiz Fernando da Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:33:18