写点什么

React Table 表格组件使用教程 排序、分页、搜索过滤筛选功能实战开发

作者:蒋川
  • 2022 年 7 月 12 日
  • 本文字数:13608 字

    阅读完需:约 45 分钟

React Table 表格组件使用教程 排序、分页、搜索过滤筛选功能实战开发

本文完整版:《React Table 表格组件使用教程 排序、分页、搜索过滤筛选功能实战开发


在日常开发中,特别是内部使用的后台系统时,我们常常会需要用表格来展示数据,同时提供一些操作用于操作表格内的数据。简单的表格直接用原生 HTML table 就好,但如果要在 React 中实现一个功能丰富的表格,其实是非常不容易的。


在本站之前的文章《最好的 6 个 React Table 组件详细亲测推荐》 中有提到过 react-table 这个库,如果对这个库不太了解的同学可以先了解一下,这里不再赘述。


简而言之,react-table 是一个非常强大的库,它与常见的表格组件不同,它不负责渲染 HTML 和 CSS,而是提供了一系列的 hooks 让我们可以灵活地构建功能强大的表格组件。


因此使用 react-table 进行开发具有一定的难度,而本文将由浅入深地讲解如何在 React 项目中使用 react-table 实现各种常见的需求,例如:排序、分页、搜索过滤筛选等;同时还会结合一个完整的案例给大家讲解如何搭配使用 Material-UI 以及模拟从后端获取数据进行分页等功能。


如果你正在搭建后台管理工具,又不想处理前端问题,推荐使用卡拉云 ,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API,内置表格等常见的前端组件,无需懂前端,仅需拖拽即可快速搭建属于你自己的后台管理工具,一周工作量缩减至一天,详见本文文末。


跟随本文你将学到


  • 如何使用 react-table 在 React 中搭建表格组件

  • 如何使用 react-table 表格组件进行数据的分页、排序、搜索过滤筛选

  • react-table 实战案例:手把手教你使用 react-table 表格组件实战分页、排序、搜索过滤筛选



扩展阅读:《顶级好用的 React 表单设计生成器,可拖拽生成表单

react-table 安装和使用

首先,让我们先来创建一个 React 项目:


npx create-react-app react-table-demo
cd react-table-demo
复制代码


然后我们安装一下 react-table:


接下来我们通过一个简单的示例,讲解如何在 React 项目中使用 react-table。


假设我们有一个订单表:



我们使用 react-table 时,需要通过一个叫做 useTable 的 hooks 来构建表格。


import { useTable } from 'react-table'
复制代码


useTable 接收两个必填的参数:


  1. data:表格的数据

  2. columns:表格的列


所以让我们先来定义这个订单表的 data 和 columns:


import React, { useMemo } from 'react'
function App() { const data = useMemo( () => [ { name: '蒋铁柱', address: '北京市海淀区西三环中路19号', date: '2022-07-01', order: '1596694478675759682' }, { name: '陈成功', address: '湖北武汉武昌区天子家园', date: '2022-06-27', order: '1448752212249399810' }, { name: '宋阿美', address: '湖北武汉武昌区天子家园', date: '2022-06-21', order: '1171859737495400477' }, { name: '张小乐', address: '北京市海淀区北航南门', date: '2022-06-30', order: '1096242976523544343' }, { name: '马国庆', address: '北京市海淀区花园桥东南', date: '2022-06-12', order: '1344783976877111376' }, { name: '小果', address: '广州天河机场西侧停车场', date: '2022-06-07', order: '1505069508845600364' } ], [] )
const columns = useMemo( () => [ { Header: '订单编号', accessor: 'order' }, { Header: '姓名', accessor: 'name' }, { Header: '收货地址', accessor: 'address' }, { Header: '下单日期', accessor: 'date' } ], [] )
return ( <div> <h1>React Table Demo —— 卡拉云(https://kalacloud.com)</h1> <Table columns={columns} data={data}></Table> </div> )}
复制代码


你可能会注意到这里我们使用 useMeno 来声明数据,这是因为 react-table 文档中说明传入的 data 和 columns 必须是 memoized 的,简单来说就是可以缓存的,仅当依赖项数组里面的依赖发生变化时才会重新计算,如果对 useMemo 不熟悉的同学建议直接看 React 文档


接着我们构建一个 Table 组件接收 columns 和 data,并传入到 useTable 中,它会返回一系列属性,我们就可以利用这些属性来构建 HTML table:


function Table({ columns, data }) {  const {    getTableProps,    getTableBodyProps,    headerGroups,    rows,    prepareRow,  } = useTable({    columns,    data,  })
return ( <table {...getTableProps()}> <thead> {headerGroups.map((headerGroup) => ( <tr {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map((column) => ( <th {...column.getHeaderProps()}>{column.render('Header')}</th> ))} </tr> ))} </thead> <tbody {...getTableBodyProps()}> {rows.map((row, i) => { prepareRow(row) return ( <tr {...row.getRowProps()}> {row.cells.map((cell) => { return <td {...cell.getCellProps()}>{cell.render('Cell')}</td> })} </tr> ) })} </tbody> </table> )}
复制代码


由于是使用原生的 HTML table,因此是没有任何样式的, 这也是 react-table 的特点,好处是我们可以随意自定义我们想要的样式,比如我们引入 github-markdown-css


npm i github-markdown-css
复制代码


然后在项目中使用即可:


import React, { useMemo } from 'react'import { useTable } from 'react-table'
import './App.css'+ import 'github-markdown-css'
function App() { return (- <div>+ <div className="markdown-body" style={{ padding: '20px' }}> <h1>React Table Demo —— 卡拉云(https://kalacloud.com)</h1> <Table columns={columns} data={data}></Table> </div> )}
复制代码


react-table 样式效果:



接下来我们给这个表格添加更多常见的功能:排序、搜索过滤筛选、分页等。


扩展阅读:《7 款最棒的开源 React 移动端 UI 组件库和模版框架 - 特别针对国内使用场景推荐》

React Table 表格排序功能

如果只是想设置默认排序,我们可以通过配置 initialState 来实现:


useTable({  columns,  data,  initialState: {    sortBy: [      {        id: 'order',        desc: true      }    ]  }})
复制代码


如果要实现手动排序,就需要通过 useSortBy 这个 hooks 实现:


import { useTable, useSortBy } from 'react-table' 
复制代码


然后在 useTable 中传入 useSortBy


const {  getTableProps,  getTableBodyProps,  headerGroups,  rows,  prepareRow,} = useTable( {   columns,   data, },+ useSortBy,)
复制代码


然后我们可以在 columns 中的某个列指定 sortType 属性,它接收 String 或 Function,对于 Function 的使用方式按下不表,而对于 String 类型,它可以接收以下三种:


  1. alphanumeric:字母或数字进行排序(默认值)

  2. basic:0 到 1 之间的数字排序

  3. datetime:日期排序,值必须为 Date 类型


比如在我们这个例子中,我们希望可以允许对「订单编号」进行排序,那我们则修改:


const columns = useMemo(  () => [    {      Header: '订单编号',      accessor: 'order',+     sortType: 'basic'    },    {      Header: '姓名',      accessor: 'name'    },    {      Header: '收货地址',      accessor: 'address'    },    {      Header: '下单日期',      accessor: 'date',    }  ],  [])
复制代码


接着我们在表头处中添加排序相关的逻辑,并且根据当前列的排序情况分别显示对应的箭头,或者在没有任何排序时不显示:


<thead>  {headerGroups.map((headerGroup) => (  <tr {...headerGroup.getHeaderGroupProps()}>    {headerGroup.headers.map((column) => (-   <th {...column.getHeaderProps()}>+   <th {...column.getHeaderProps(column.getSortByToggleProps())}>      {column.render('Header')}+     <span>+       {column.isSorted ? (column.isSortedDesc ? ' 🔽' : ' 🔼') : ''}+     </span>    </th>    ))}  </tr>  ))}</thead>
复制代码


展示效果如下:



通过上图我们发现了一个问题:即便我们没有对「姓名」这一列配置 sortType,却依然可以进行排序,这是因为一旦在 useTable 传入了 useSortBy,则默认所有列都可进行排序,如果我们需要对特定的列禁用排序,可以这样:


const columns = useMemo(  () => [    {      Header: '订单编号',      accessor: 'order',      sortType: 'basic'    },    {      Header: '姓名',      accessor: 'name',+     disableSortBy: true,    },    {      Header: '收货地址',      accessor: 'address'    },    {      Header: '下单日期',      accessor: 'date',    }  ],  [])
复制代码


关于排序功能更多详细细节参见文档:useSortBy


扩展阅读:《7 款最棒的开源 React UI 组件库和模版框架测评 - 特别针对国内使用场景推荐

React Table 表格搜索过滤筛选功能

我们可以通过 useFilters 来实现筛选功能:


import { useTable, useFilters } from 'react-table'
复制代码


同样地,需要在 useTable 中传入:


const {  getTableProps,  getTableBodyProps,  headerGroups,  rows,  prepareRow,} = useTable( {   columns,   data, },+ useFilters,)
复制代码


PS:注意 useFilters 必须位于 useSortBy 前面,否则会报错。


然后在表头中渲染筛选输入框:


<th {...column.getHeaderProps()}> {column.render('Header')}+ <div>{column.canFilter ? column.render('Filter') : null}</div></th>
复制代码


这个筛选输入框的 UI 需要我们自定义,所以我们定义一个 TextFilter 组件:


function TextFilter({ column: { filterValue, preFilteredRows, setFilter } }) {  const count = preFilteredRows.length
return ( <input value={filterValue || ''} onChange={(e) => { setFilter(e.target.value || undefined) }} placeholder={`筛选 ${count} 条记录`} /> )}
复制代码


这个组件接收三个参数:


  • filterValue:用户输入的筛选值

  • preFilteredRows:筛选前的行

  • setFilter:用于设置用户筛选的值


定义完筛选组件后,我们还将 TextFilter 传入到一个 defaultColumn 中:


const defaultColumn = React.useMemo( () => ({   Filter: TextFilter, }), [])
复制代码


接着再把 defaultColumn 传入 useTable


const {  getTableProps,  getTableBodyProps,  headerGroups,  rows,  prepareRow,} = useTable( {   columns,   data,+  defaultColumn, }, useFilters,)
复制代码


展示效果如下:



这里我们发现了一个问题:当点击筛选输入框时,会改变排序方式,这是因为改变排序的点击事件是放在 <th>,因此我们要阻止这个输入框的点击事件向外层冒泡:


- <div>+ <div onClick={(e) => e.stopPropagation()}>    {column.canFilter ? column.render('Filter') : null}</div>
复制代码


同样地,如果想要禁用某一个列的筛选,可以设置 disableFilters


const columns = useMemo(  () => [    {      Header: '订单编号',      accessor: 'order',      sortType: 'basic'    },    {      Header: '姓名',      accessor: 'name',+     disableFilters: true,    },    {      Header: '收货地址',      accessor: 'address'    },    {      Header: '下单日期',      accessor: 'date',    }  ],  [])
复制代码


关于筛选功能更多详细细节参见文档:useFilters


扩展阅读:《最好用的 8 款 React Datepicker 时间日期选择器测评推荐》

React Table 表格分页功能

分页功能使用 usePagination 这个 hooks 实现:


import { useTable, usePagination } from 'react-table' 
复制代码


然后在 useTable 中添加分页相关的参数:


const {   getTableProps,   headerGroups,   getRowProps,-  rows +  state: { pageIndex, pageSize },+  canPreviousPage,+  canNextPage,+  previousPage,+  nextPage,+  pageOptions,+  page } = useTable(   {     columns,     data,+    initialState: { pageSize: 2 },   },+  usePagination, )
复制代码


然后我们 tbody 中的 rows 将从 page 变量中获取:


<tbody {...getTableBodyProps()}>- {rows.map((row) => {+ {page.map((row) => {      prepareRow(row)  return (    <tr {...row.getRowProps()}>      {row.cells.map((cell) => {        return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>      })}    </tr>  )})}</tbody>
复制代码


我们还需要构建一个分页器:


function Pagination({  canPreviousPage,  canNextPage,  previousPage,  nextPage,  pageOptions,  pageIndex}) {  return (    <div>      <button onClick={() => previousPage()} disabled={!canPreviousPage}>        上一页      </button>{' '}      <button onClick={() => nextPage()} disabled={!canNextPage}>        下一页      </button>      <div>        第{' '}        <em>          {pageIndex + 1} / {pageOptions.length}        </em>{' '}      </div>    </div>  )}
复制代码


在 table 后面使用这个分页器:


<>  <table {...getTableProps()}>...  </table>  <Pagination    canPreviousPage={canPreviousPage}    canNextPage={canNextPage}    previousPage={previousPage}    nextPage={nextPage}    pageOptions={pageOptions}    pageIndex={pageIndex}  /></>
复制代码


展示效果如下:



更复杂的分页可以参考官方示例:Examples: Pagination


扩展阅读:《最好用的 5 个 React select 多选下拉菜单组件测评推荐》

React table 排序、搜索过滤筛选、分页示例代码

通过前文我们已经把 react-table 的基本使用都演示了一遍,你可以在此获取示例代码。

React table 实战案例

但是实际开发中的需求自然不会满足于本地数据,因此接下来我们演示一个更加真实、完整的例子,它将包含以下功能:


  1. 模拟从远端请求数据,并且通过服务端进行分页、筛选、排序。

  2. 搭配 Material-UI 构建组件


首先创建一个新的项目:


npx create-react-app react-table-example
cd react-table-example
复制代码


然后安装相关依赖:


npm i react-table mockjs axios lodash.orderby
npm i axios-mock-adapter --save-dev
npm i @material-ui/core @material-ui/icons
复制代码

模拟 API

然后我们生成 200 条订单数据,同时模拟 API 的筛选、排序和分页功能:


// mock.js
import axios from 'axios'import MockAdapter from 'axios-mock-adapter'import Mock from 'mockjs'import _orderby from 'lodash.orderby'
const { Random, mock } = Mock
const orders = new Array(200).fill(null).map(() => { return mock({ order: Random.natural(), name: Random.cname(), address: Random.province() + '-' + Random.city() + '-' + Random.county(), date: Random.date() })})
const mockAPI = { start() { const mock = new MockAdapter(axios)
mock.onGet('/api/orders').reply((config) => { let { filter, sortBy, page = 0, size = 10 } = config.params || {}
let mockOrders = [...orders]
if (filter) { mockOrders = orders.filter((order) => { return Object.values(order).some((value) => value.includes(filter)) }) }
if (sortBy.length) { sortBy.forEach((sort) => { mockOrders = _orderby( mockOrders, [sort.id], [sort.desc ? 'desc' : 'asc'] ) }) }
const offset = page * size
mockOrders = mockOrders.slice(offset, offset + size)
return new Promise((resolve) => { setTimeout(() => { resolve([ 200, { data: mockOrders, total_count: orders.length } ]) }, 500) }) }) }}
export default mockAPI
复制代码


然后在 App.js 中引入并开始 mock 数据:


import mockAPI from './mock'
mockAPI.start()
复制代码

构建基础 React Table 组件

有了上面的经验,我们很快就可以构建一个基础的表格组件:


// components/Table.js
import React from 'react'
import { useTable } from 'react-table'
import MaUTable from '@material-ui/core/Table'import TableBody from '@material-ui/core/TableBody'import TableCell from '@material-ui/core/TableCell'import TableContainer from '@material-ui/core/TableContainer'import TableHead from '@material-ui/core/TableHead'import TableRow from '@material-ui/core/TableRow'
function Table({ columns, data }) { const { getTableProps, headerGroups, prepareRow, rows } = useTable({ columns, data })
return ( <TableContainer> <MaUTable {...getTableProps()}> <TableHead> {headerGroups.map((headerGroup) => ( <TableRow {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map((column) => ( <TableCell {...column.getHeaderProps()}> {column.render('Header')} </TableCell> ))} </TableRow> ))} </TableHead> <TableBody> {rows.map((row, i) => { prepareRow(row) return ( <TableRow {...row.getRowProps()}> {row.cells.map((cell) => { return ( <TableCell {...cell.getCellProps()}> {cell.render('Cell')} </TableCell> ) })} </TableRow> ) })} </TableBody> </MaUTable> </TableContainer> )}
export default Table
复制代码


然后在 App.js 中请求 API 并展示:


import React, { useState, useMemo, useEffect } from 'react'import axios from 'axios'
import Table from './components/Table'
import mockAPI from './mock'
mockAPI.start()
function App() { const fetchOrders = async (params = {}) => { return axios.get('/api/orders', { params }).then((res) => { const resp = res.data
setOrders(resp.data) }) }
const [orders, setOrders] = useState([])
const data = useMemo(() => { return [...orders] }, [orders])
const columns = useMemo( () => [ { Header: '订单编号', accessor: 'order' }, { Header: '姓名', accessor: 'name' }, { Header: '收货地址', accessor: 'address' }, { Header: '下单日期', accessor: 'date' } ], [] ) useEffect(() => { fetchOrders() }, [])
return ( <div style={{ padding: '20px' }}> <h1>React Table Example —— 卡拉云(https://kalacloud.com)</h1> <Table data={data} columns={columns} /> </div> )}
export default App
复制代码


展示效果如下:


服务端分页

接着我们添加分页功能,首先添加 TablePaginationActions 组件:


// components/TablePaginationActions.js
import React from 'react'
import FirstPageIcon from '@material-ui/icons/FirstPage'import IconButton from '@material-ui/core/IconButton'import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft'import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight'import LastPageIcon from '@material-ui/icons/LastPage'import { makeStyles, useTheme } from '@material-ui/core/styles'
const useStyles = makeStyles((theme) => ({ root: { flexShrink: 0, marginLeft: theme.spacing(2.5) }}))
const TablePaginationActions = (props) => { const classes = useStyles() const theme = useTheme() const { count, page, rowsPerPage, onPageChange } = props
const handleFirstPageButtonClick = (event) => { onPageChange(event, 0) }
const handleBackButtonClick = (event) => { onPageChange(event, page - 1) }
const handleNextButtonClick = (event) => { onPageChange(event, page + 1) }
const handleLastPageButtonClick = (event) => { onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1)) }
return ( <div className={classes.root}> <IconButton onClick={handleFirstPageButtonClick} disabled={page === 0} aria-label="first page" > {theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />} </IconButton> <IconButton onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page" > {theme.direction === 'rtl' ? ( <KeyboardArrowRight /> ) : ( <KeyboardArrowLeft /> )} </IconButton> <IconButton onClick={handleNextButtonClick} disabled={page >= Math.ceil(count / rowsPerPage) - 1} aria-label="next page" > {theme.direction === 'rtl' ? ( <KeyboardArrowLeft /> ) : ( <KeyboardArrowRight /> )} </IconButton> <IconButton onClick={handleLastPageButtonClick} disabled={page >= Math.ceil(count / rowsPerPage) - 1} aria-label="last page" > {theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />} </IconButton> </div> )}
export default TablePaginationActions
复制代码


然后在 Table.js 中修改如下:


import React, { useEffect } from 'react'import { useTable, usePagination } from 'react-table'
+ import TableFooter from '@material-ui/core/TableFooter'+ import TablePagination from '@material-ui/core/TablePagination'+ import TablePaginationActions from './TablePaginationActions'
- function Table({ columns, data }) {+ function Table({ columns, data, totalCount, onStateChange }) { const { getTableProps, headerGroups, prepareRow,- rows, + page,+ gotoPage,+ setPageSize,+ state: { pageIndex, pageSize } } = useTable( { columns, data,+ manualPagination: true,+ pageCount: totalCount },+ usePagination )
+ useEffect(() => {+ onStateChange({ pageIndex, pageSize })+ }, [pageIndex, pageSize, onStateChange])
+ const handleChangePage = (event, newPage) => {+ gotoPage(newPage)+ }
+ const handleChangeRowsPerPage = (event) => {+ setPageSize(Number(event.target.value))+ }
return ( <TableContainer> <MaUTable {...getTableProps()}>... <TableBody>- {rows.map((row, i) => {+ {page.map((row, i) => {... </TableBody>
+ <TableFooter>+ <TableRow>+ <TablePagination+ rowsPerPageOptions={[5, 10, 15, 20]}+ colSpan={3}+ count={totalCount}+ rowsPerPage={pageSize}+ page={pageIndex}+ SelectProps={{+ inputProps: { 'aria-label': 'rows per page' },+ native: true+ }}+ onPageChange={handleChangePage}+ onRowsPerPageChange={handleChangeRowsPerPage}+ ActionsComponent={TablePaginationActions}+ />+ </TableRow>+ </TableFooter> </MaUTable> </TableContainer> )}
export default Table
复制代码


App.js 中增加控制分页的逻辑:


const [totalCount, setTotalCount] = useState(0)
const fetchOrders = async (params = {}) => { return axios.get('/api/orders', { params }).then((res) => { const resp = res.data
setOrders(resp.data) setTotalCount(resp.total_count) })}
const onStateChange = useCallback(({ pageIndex, pageSize }) => { fetchOrders({ page: pageIndex, size: pageSize })}, [])
复制代码


由于 Table 组件内部会触发 onStateChange,因此不需要在 useEffect 中获取数据 ,然后传入 Table 相关属性:


- useEffect(() => {-     fetchOrders()-   }, [])
<Table data={data} columns={columns}+ totalCount={totalCount}+ onStateChange={onStateChange}/>
复制代码


展示效果如下:


服务端排序

接着我们添加排序功能,首先修改 Table.js


- import { useTable, usePagination } from 'react-table'+ import { useTable, usePagination, useSortBy } from 'react-table'
+ import TableSortLabel from '@material-ui/core/TableSortLabel'
function Table({ columns, data, totalCount, onStateChange }) { const { getTableProps, headerGroups, prepareRow, page, gotoPage, setPageSize,- state: { pageIndex, pageSize } + state: { pageIndex, pageSize, sortBy } } = useTable( { columns, data, manualPagination: true,+ manualSortBy: true, pageCount: totalCount },+ useSortBy, usePagination ) - useEffect(() => {- onStateChange({ pageIndex, pageSize })- }, [pageIndex, pageSize, onStateChange])
+ useEffect(() => {+ onStateChange({ pageIndex, pageSize, sortBy })+ }, [pageIndex, pageSize, sortBy, onStateChange])

<TableCell- {...column.getHeaderProps()}+ {...column.getHeaderProps(column.getSortByToggleProps())} > {column.render('Header')}+ <TableSortLabel+ active={column.isSorted}+ direction={column.isSortedDesc ? 'desc' : 'asc'}+ /> </TableCell>}
复制代码


React table 排序功能展示效果如下:



扩展阅读:《React 实现 PDF 文件在线预览 - 手把手教你写 React PDF 预览功能》

服务端搜索过滤筛选

然后我们添加筛选功能,通常筛选器都是位于表格以外的,在本例子中,我们期待在筛选框中输入的搜索值应用在所有的列,这里我们创建一个 TableFilter 组件:


// components/TableFilter.js
import React from 'react'
import InputBase from '@material-ui/core/InputBase'import { fade, makeStyles } from '@material-ui/core/styles'import SearchIcon from '@material-ui/icons/Search'
const useStyles = makeStyles((theme) => ({ search: { position: 'relative', borderRadius: theme.shape.borderRadius, backgroundColor: fade(theme.palette.common.white, 0.15), '&:hover': { backgroundColor: fade(theme.palette.common.white, 0.25) }, marginRight: theme.spacing(2), marginLeft: 0, width: '100%', [theme.breakpoints.up('sm')]: { width: 'auto' } }, searchIcon: { width: theme.spacing(7), height: '100%', position: 'absolute', pointerEvents: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center' }, inputRoot: { color: 'inherit' }, inputInput: { padding: theme.spacing(1, 1, 1, 7), transition: theme.transitions.create('width'), width: '100%', [theme.breakpoints.up('md')]: { width: 200 } }}))
const GlobalFilter = ({ globalFilter, setGlobalFilter }) => { const classes = useStyles()
return ( <div className={classes.search}> <div className={classes.searchIcon}> <SearchIcon /> </div> <InputBase value={globalFilter || ''} onChange={(e) => { setGlobalFilter(e.target.value || undefined) }} placeholder={`在此输入搜索值`} classes={{ root: classes.inputRoot, input: classes.inputInput }} inputProps={{ 'aria-label': 'search' }} /> </div> )}
export default GlobalFilter
复制代码


然后在 Table.js 中使用这个组件,并添加筛选逻辑:


- import { useTable, usePagination, useSortBy } from 'react-table'+ import { useTable, usePagination, useSortBy, useGlobalFilter } from 'react-table'
+ import TableFilter from './TableFilters'
function Table({ columns, data, totalCount, onStateChange }) { const { getTableProps, headerGroups, prepareRow, page, gotoPage, setPageSize,- state: { pageIndex, pageSize, sortBy } + state: { pageIndex, pageSize, sortBy, globalFilter },+ setGlobalFilter } = useTable( { columns, data, manualPagination: true, manualSortBy: true,+ manualGlobalFilter: true, pageCount: totalCount },+ useGlobalFilter, useSortBy, usePagination ) useEffect(() => {- onStateChange({ pageIndex, pageSize, sortBy })+ onStateChange({ pageIndex, pageSize, sortBy, filter: globalFilter })- }, [pageIndex, pageSize, sortBy, onStateChange])+ }, [pageIndex, pageSize, sortBy, onStateChange, globalFilter]) <TableContainer>+ <TableFilter+ globalFilter={globalFilter}+ setGlobalFilter={setGlobalFilter}+ />
复制代码


App.js 中接收 filter 值并传递给 API:


const onStateChange = useCallback(- ({ pageIndex, pageSize, sortBy }) => {+ ({ pageIndex, pageSize, sortBy, filter }) => {    fetchOrders({      page: pageIndex,      size: pageSize,      sortBy,+     filter    })  },  [])
复制代码


react-table 搜索过滤筛选展示效果如下:



扩展阅读:《5款 React 实时消息提示通知(Message/Notification)组件推荐与测评

React Table 组件与卡拉云

前面我们展示了如何在 react-table 中搭配 Material-UI 构建一个完整的表格组件,相信你已经上手 react-table 的用法,而这只是 react-table 功能的冰山一角,还有更多例如:动态展示列、分组展开、动画、拖拽、行内编辑、虚拟列表等,所以 react-table 的强大可以让你搭配出更多自定义功能。


其实如果你只想专注在解决问题,而不想把时间浪费在调试前端问题上的话,推荐使用卡拉云,卡拉云是新一代低代码开发工具,不仅可以拖拽生成带有排序、分页、搜索功能的表格组件等多种你需要的前端组件。与各类前端框架相比,卡拉云完全不用写前端代码,极大提升了开发效率,1 周的工作量,现在只要 30 分钟即可完成。卡拉云直接注册即可开始使用,后台搭建完成后,还能一键分享给同事一起使用。


可一键分享给同事一起使用:https://my.kalacloud.com/apps/q6p23cqa29/published


卡拉云可帮你快速搭建企业内部工具,下图为使用卡拉云搭建的内部广告投放监测系统,无需懂前端,仅需拖拽组件,10 分钟搞定。你也可以快速搭建一套属于你的后台管理工具。



卡拉云是新一代低代码开发平台,与前端框架 Vue、React 等相比,卡拉云的优势在于不用首先搭建开发环境,直接注册即可开始使用。开发者完全不用处理任何前端问题,只需简单拖拽,即可快速生成所需组件,可一键接入常见数据库及 API,根据引导简单几步打通前后端,数周的开发时间,缩短至 1 小时。立即免费试用卡拉云

发布于: 刚刚阅读数: 3
用户头像

蒋川

关注

我的微信:HiJiangChuan 2020.09.08 加入

卡拉云 CMO 卡拉云是一套帮助后端程序员搭建企业内部工具的系统,欢迎试用 www.kalacloud.com

评论

发布
暂无评论
React Table 表格组件使用教程 排序、分页、搜索过滤筛选功能实战开发_排序_蒋川_InfoQ写作社区