Replies: 2 comments
|
A Solid resource should be handled the same way as a signal here: read the accessor inside the const emptyRows: Person[] = []
const [rows] = createResource(fetchRows)
const table = createTable({
features,
columns: props.columns(),
get data() {
return rows() ?? emptyRows
},
})If the resource is passed through a prop, pass the accessor and call it in the getter, e.g. |
|
The reason it works with a signal but appears "stuck" with a resource almost always comes down to how the resource accessor is passed and where it is tracked in Solid's reactive graph. In Solid, component bodies only run once. If reactivity is lost at the prop boundary or if Here is the exact breakdown and the robust pattern to get it working reliably: Pitfall 1: Calling the Resource Accessor in the Parent JSXIf the parent does: // ❌ WRONG: Calls the accessor once during parent mount when resource is still undefined
<TableComponent data={resource()} />
Instead, pass the accessor itself: // ✅ CORRECT: Passes the getter function so the child can track it reactively
<TableComponent data={resource} />Pitfall 2: Reading Rows Outside a Reactive Tracking ContextIf you assign rows to a local variable in the component body: // ❌ WRONG: Evaluated once at mount before the resource finishes fetching
const rows = table.getRowModel().rows;
return (
<tbody>
<For each={rows}>...</For>
</tbody>
);
Instead, pass // ✅ CORRECT: Solid tracks property access inside <For>'s reactive computation
<tbody>
<For each={table.getRowModel().rows}>
{(row) => (
<tr>
<For each={row.getVisibleCells()}>
{(cell) => (
<td>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
)}
</For>
</tr>
)}
</For>
</tbody>Complete Working Implementationimport { createResource, For, Show, Suspense, type Accessor } from 'solid-js';
import {
createTable,
getCoreRowModel,
flexRender,
type ColumnDef,
} from '@tanstack/solid-table';
interface Props<T> {
// Accept the resource accessor directly
data: Accessor<T[] | undefined>;
columns: ColumnDef<T>[];
}
export function DataTable<T>(props: Props<T>) {
// Empty fallback array to preserve object identity across renders
const defaultData: T[] = [];
const table = createTable({
// TanStack Table v9 options
get data() {
// Calling props.data() here tracks the Solid resource dependency
return props.data() ?? defaultData;
},
columns: props.columns,
getCoreRowModel: getCoreRowModel(),
});
return (
<div class="table-container">
<table>
<thead>
<For each={table.getHeaderGroups()}>
{(headerGroup) => (
<tr>
<For each={headerGroup.headers}>
{(header) => (
<th>
<Show when={!header.isPlaceholder}>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</Show>
</th>
)}
</For>
</tr>
)}
</For>
</thead>
<tbody>
{/* Direct property access inside <For> guarantees fine-grained re-renders */}
<For each={table.getRowModel().rows}>
{(row) => (
<tr>
<For each={row.getVisibleCells()}>
{(cell) => (
<td>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
)}
</For>
</tr>
)}
</For>
</tbody>
</table>
</div>
);
}
// In your parent page / component:
export function UserPage() {
const [users] = createResource(fetchUsers);
return (
<Suspense fallback={<p>Loading users...</p>}>
{/* Pass accessor without invoking it */}
<DataTable data={users} columns={columns} />
</Suspense>
);
}Key Takeaways:
|
Uh oh!
There was an error while loading. Please reload this page.
Hi,
I want to know how to use tanstack table with solid's createResource.
when 'data' is a signal, I found below works:
however, it does not work when data is a resource. after the resource settles from undefined and the data is populated, the tanstack table does not update with the data.
Any help would be appreciated :)
All reactions