在Next.js中实现Tanstack Table表头与单元格宽度自适应
解决Tanstack Table v8最后一列被隐藏的响应式问题
问题原因
Tailwind CSS的固定15rem宽度限制了表格容器,导致列数较多时最后一列被挤出可视区域。要实现响应式,需让表格宽度自适应内容,同时在小屏幕上支持横向滚动。
修复步骤
1. 给表格容器添加横向滚动
修改包裹<Table>的外层div,添加overflow-x-auto类移除固定宽度限制,确保内容超出时可横向滚动:
<div className="rounded-md border overflow-x-auto"> <Table> {/* 表格内容 */} </Table> </div>
2. 配置列宽为自适应
在列定义中,给常规列设置width: "auto"让其自适应内容宽度,给操作列设置固定窄宽度避免占用过多空间:
const columns: ColumnDef<IUSER>[] = [ { accessorKey: "name", width: "auto", header: ({ column }) => { /* 原代码 */ }, }, // 其他列同样添加width: "auto" { accessorKey: "id", header: "Action", width: 120, // 操作列固定窄宽度 cell: (rowData) => { /* 原代码 */ }, }, ];
3. 优化单元格内边距
替换TableCell上过大的pl-8内边距为紧凑的px-4 py-2,减少横向空间占用:
<TableCell key={cell.id} className="px-4 py-2"> {flexRender(cell.column.columnDef.cell, cell.getContext())} </TableCell>
4. 可选:启用自动列宽计算
引入getAutoSizeRowModel让表格根据内容自动计算精确列宽:
import { getAutoSizeRowModel } from "@tanstack/react-table"; const table = useReactTable({ // ...其他配置 getAutoSizeRowModel: getAutoSizeRowModel(), });
完整修改后的代码示例
列定义代码
const columns: ColumnDef<IUSER>[] = [ { accessorKey: "name", width: "auto", header: ({ column }) => { return ( <Button variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Name {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />} </Button> ); }, }, { accessorKey: "location", width: "auto", header: ({ column }) => { return ( <Button variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Location {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />} </Button> ); }, }, { accessorKey: "gender", width: "auto", header: ({ column }) => { return ( <Button variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Gender {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />} </Button> ); }, }, { accessorKey: "accCreationDate", width: "auto", cell: (props) => <span>{formatDateValue(props.getValue())}</span>, header: ({ column }) => { return ( <Button variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Created Date {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />} </Button> ); }, }, { accessorKey: "uniqueId", width: "auto", header: ({ column }) => { return ( <Button variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Unique Id {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />} </Button> ); }, }, { accessorKey: "email", width: "auto", header: ({ column }) => { return ( <Button variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Email {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />} </Button> ); }, }, { accessorKey: "number", width: "auto", header: ({ column }) => { return ( <Button variant="ghost" onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} > Contact No {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />} </Button> ); }, }, { accessorKey: "id", header: "Action", width: 120, cell: (rowData) => { const { id } = rowData.row.original as IUSER; return ( <Link href={`/details/${id}`} className="text-blue-600"> View Details </Link> ); }, }, ];
表格初始化与渲染代码
import { getAutoSizeRowModel } from "@tanstack/react-table"; const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), getAutoSizeRowModel: getAutoSizeRowModel(), onSortingChange: setSorting, getSortedRowModel: getSortedRowModel(), state: { sorting, }, }); return ( <div className="rounded-md border overflow-x-auto"> <Table> <TableHeader className="bg-slate-200"> {table.getHeaderGroups().map((headerGroup) => ( <TableRow key={headerGroup.id}> {headerGroup.headers.map((header) => { return ( <TableHead key={header.id}> {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} </TableHead> ); })} </TableRow> ))} </TableHeader> <TableBody> {table.getRowModel()?.rows?.length ? ( table.getRowModel().rows.map((row) => ( <TableRow key={row.id} data-state={row.getIsSelected() && "selected"} > {row.getVisibleCells().map((cell) => ( <TableCell key={cell.id} className="px-4 py-2"> {flexRender(cell.column.columnDef.cell, cell.getContext())} </TableCell> ))} </TableRow> )) ) : ( <TableRow> <TableCell colSpan={columns.length} className="h-24 text-center"> No Data </TableCell> </TableRow> )} </TableBody> </Table> </div> );
内容的提问来源于stack exchange,提问作者Hello World
相关产品推荐
相关产品推荐

