在Solidjs中使用TanStack Table实现复选框遇更新异常
问题背景
在SolidJS中使用TanStack Table构建表格时,复选框列的状态无法随行选择操作更新。尝试复用React Table示例代码,以及自行通过createSignal维护选中状态(但违背了TanStack Table管理状态的初衷)均未解决问题,核心原因是未正确结合SolidJS的响应式机制追踪TanStack Table的状态变化。
错误尝试代码
基于TanStack API的无效实现:
const checkbox = { accessorKey: "checkbox", header: (props) => ( <Checkbox {...{ checked: props.table.getIsAllRowsSelected(), indeterminate: props.table.getIsSomeRowsSelected(), onChange: props.table.getToggleAllRowsSelectedHandler(), }} /> ), cell: (props) => { return ( <Checkbox {...{ checked: props.row.getIsSelected(), disabled: !props.row.getCanSelect(), onChange: props.row.getToggleSelectedHandler(), }} /> ); }, };
自行维护状态的非预期实现:
cell: () => { const [isSelected , setIsSelected] = createSignal(false) const toggleSelected = (event , checked) => { setIsSelected(checked) } return ( <Checkbox {...{ checked: isSelected(), onChange: toggleSelected, }} /> ); },
修正后的完整代码
const generateColumns = (columns) => { const result = columns.map((value) => { return { accessorKey: value, }; }); return result; }; const DataTable = (props) => { const [rowSelection, setRowSelection] = createSignal({}); const checkbox = { accessorKey: "checkbox", header: (props) => ( <Checkbox checked={props.table.getIsAllRowsSelected()} indeterminate={props.table.getIsSomeRowsSelected()} onChange={props.table.getToggleAllRowsSelectedHandler()} /> ), cell: (props) => ( <Checkbox checked={props.row.getIsSelected()} disabled={!props.row.getCanSelect()} onChange={props.row.getToggleSelectedHandler()} /> ), }; const columns = [checkbox, ...generateColumns(props.columns)]; const table = createSolidTable({ get data() { return props.data; }, columns: columns, state: { get rowSelection() { return rowSelection(); }, }, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), }); return ( <TableContainer component={Paper}> <Table> <TableHead> <For each={table.getHeaderGroups()}> {(headerGroup) => ( <TableRow> <For each={headerGroup.headers}> {(header) => ( <TableCell> {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} </TableCell> )} </For> </TableRow> )} </For> </TableHead> <TableBody> <For each={table.getRowModel().rows}> {(row) => ( <TableRow> <For each={row.getVisibleCells()}> {(cell) => <TableCell>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>} </For> </TableRow> )} </For> </TableBody> </Table> </TableContainer> ); };
关键修复点
正确调用状态获取函数
在表头和单元格的复选框配置中,确保调用getIsAllRowsSelected()、getIsSomeRowsSelected()、getIsSelected()这些函数(而非直接传递函数引用)。SolidJS的响应式系统会追踪这些函数调用,当rowSelection状态变化时自动触发视图更新。复用TanStack的选择处理函数
放弃自行通过createSignal维护状态,直接使用getToggleAllRowsSelectedHandler()和getToggleSelectedHandler()处理切换事件。这些函数会自动更新TanStack Table的rowSelection状态,并通过onRowSelectionChange同步到响应式变量中,确保状态统一。保持响应式上下文完整
表格的data和rowSelection配置使用getter函数(get data()、get rowSelection()),确保SolidJS能正确追踪依赖变化,当props.data或rowSelection更新时,表格会重新计算行模型并更新视图。
内容的提问来源于stack exchange,提问作者danialsaufi

