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

在TanStack React Table中用URL而非状态管理globalFilter

解决方案:仅通过URL管理TanStack React Table的全局筛选状态

你完全可以仅通过URL来管理全局筛选状态,无需维护组件内部状态。核心思路是将URL的查询参数作为筛选状态的唯一数据源,所有筛选操作直接更新URL,同时利用Next.js的useSearchParams响应式特性让表格自动同步状态。

以下是重构后的完整代码:

'use client'

import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import {
  ColumnDef,
  ColumnFiltersState,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  useReactTable,
} from '@tanstack/react-table'
import { useSearchParams, useRouter } from 'next/navigation'
import { useState } from 'react'

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData>[] | null
  data: TData[] | null
}

export const DataTable = <TData extends TValue, TValue>({
  columns,
  data,
}: DataTableProps<TData, TValue>) => {
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
  const searchParams = useSearchParams()
  const router = useRouter()

  // 直接从URL获取筛选值,作为唯一数据源
  const globalFilter = searchParams.get('q') || ''

  const table = useReactTable({
    data: data || [],
    columns: columns || [],
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    onColumnFiltersChange: setColumnFilters,
    getFilteredRowModel: getFilteredRowModel(),
    state: {
      columnFilters,
      // 使用URL中的值作为表格的全局筛选状态
      globalFilter,
    },
    // 当表格内部触发筛选变化时,同步更新URL
    onGlobalFilterChange: (newFilter) => {
      const newParams = new URLSearchParams(searchParams)
      if (newFilter) {
        newParams.set('q', newFilter)
      } else {
        newParams.delete('q')
      }
      router.push(`?${newParams.toString()}`, { scroll: false })
    },
  })

  return (
    <div>
      <div className='flex items-center justify-end pb-4 '>
        <Input
          placeholder='Search...'
          // 输入框值直接绑定URL中的筛选参数
          value={globalFilter}
          onChange={(e) => {
            const newFilter = e.target.value
            const newParams = new URLSearchParams(searchParams)
            if (newFilter) {
              newParams.set('q', newFilter)
            } else {
              newParams.delete('q')
            }
            router.push(`?${newParams.toString()}`, { scroll: false })
          }}
          className='max-w-sm w-[250px]'
        />
      </div>
      <div>
        {/* 表格内容 */}
      </div>
      <div className='flex items-center justify-end space-x-2 py-4'>
        {/* 分页内容 */}
      </div>
    </div>
  )
}

关键改动说明:

  1. 移除全局筛选状态:删除了globalFilter的useState声明,直接从searchParams获取筛选值
  2. 表格状态绑定URL:在useReactTable的state配置中,将globalFilter设置为URL中的q参数值
  3. 同步URL更新:
    • 输入框的onChange事件直接修改URL查询参数,而非组件状态
    • 表格的onGlobalFilterChange回调也同步更新URL,确保任何触发筛选的操作都能反映到URL上
  4. 保留其他查询参数:使用URLSearchParams对象修改q参数,避免覆盖URL中可能存在的其他参数

这样修改后,URL将成为筛选状态的唯一来源:

  • 用户输入搜索内容时,URL会实时更新
  • 分享链接时,接收方打开链接就能看到对应的筛选结果
  • 浏览器前进/后退时,表格会自动同步历史中的筛选状态

内容的提问来源于stack exchange,提问作者Santi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 15:43:18