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

shadcn(TanStack)表格行选择操作Zustand Store时React钩子调用错误排查

解决React Hooks调用错误:在shadcn/TanStack表格中通过行选择操作Zustand Store

错误原因

你遇到的Invalid hook call错误,核心是违反了React Hooks的使用规则:

  • useStore是Zustand提供的React Hook,必须在函数组件的顶层作用域或者自定义Hook中调用
  • 你的onStatusChange是普通函数,在里面调用useStore,相当于在非组件顶层的位置调用Hook,直接触发了React的Hook规则校验错误

解决方法

把useStore的调用移到函数组件的顶层,提前获取需要的addItem和removeItem方法,再在事件处理函数中使用这些方法。具体步骤:

  1. 将列定义(Columns)和事件处理函数(onStatusChange)放到你的表格函数组件内部
  2. 在组件顶层调用useStore,取出操作Store的方法
  3. 在onStatusChange中直接使用已获取的方法,不再调用Hook

修正后的代码示例

import { useStore } from '@/lib/store'
import { ColumnDef, useReactTable } from '@tanstack/react-table'
import { Checkbox } from '@/components/ui/checkbox'

// 替换成你的Module类型定义
type Module = {
  id: string
  // 你的其他字段
}

export const ModuleTable = () => {
  // 组件顶层调用useStore,符合Hooks规则
  const { addItem, removeItem } = useStore()

  const onStatusChange = (isSelected: boolean, rowData: Module) => {
    if (isSelected) {
      removeItem(rowData.id)
    } else {
      addItem(rowData)
    }
  }

  // 列定义放在组件内部,能直接访问顶层的方法
  const columns: ColumnDef<Module>[] = [
    {
      id: "select",
      header: ({ table }) => (
        <Checkbox
          checked={table.getIsAllPageRowsSelected()}
          onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
          aria-label="Select all"
        />
      ),
      cell: ({ row }) => (
        <Checkbox
          checked={row.getIsSelected()}
          onCheckedChange={(value) => {
            onStatusChange(!!value, row.original)
            row.toggleSelected(!!value)
          }}
          aria-label="Select row"
        />
      ),
      enableSorting: false,
      enableHiding: false,
    },
    // 其他列配置...
  ]

  // 初始化表格(示例)
  const table = useReactTable({
    columns,
    // 你的表格数据
    data: [],
  })

  return (
    <div className="space-y-4">
      {/* 表格渲染内容 */}
      <table>
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th key={header.id}>
                  {header.isPlaceholder ? null : header.renderHeader()}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody>
          {table.getRowModel().rows.map((row) => (
            <tr key={row.id}>
              {row.getVisibleCells().map((cell) => (
                <td key={cell.id}>
                  {cell.renderCell()}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

额外优化点

  • 避免使用any类型:给row指定明确的Module类型,提升代码可读性和类型安全
  • 处理onCheckedChange的参数:Checkbox的value可能是undefined,用!!value转为布尔值,确保逻辑稳定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:12:05