Skip to content

Commit 6c3980e

Browse files
committed
chore: table helper fixes and rewrite basic examples
1 parent 2b3bb36 commit 6c3980e

File tree

16 files changed

+397
-104
lines changed

16 files changed

+397
-104
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
.DS_Store
3+
dist
4+
dist-ssr
5+
*.local
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Example
2+
3+
To run this example:
4+
5+
- `npm install` or `yarn`
6+
- `npm run start` or `yarn start`
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Vite App</title>
7+
<script type="module" src="https://cdn.skypack.dev/twind/shim"></script>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "tanstack-table-example-basic-table-helper",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"dev": "vite",
7+
"build": "vite build",
8+
"serve": "vite preview",
9+
"start": "vite",
10+
"lint": "eslint ./src"
11+
},
12+
"dependencies": {
13+
"@tanstack/react-table": "^9.0.0-alpha.10",
14+
"react": "^18.3.1",
15+
"react-dom": "^18.3.1"
16+
},
17+
"devDependencies": {
18+
"@rollup/plugin-replace": "^5.0.7",
19+
"@types/react": "^18.3.3",
20+
"@types/react-dom": "^18.3.0",
21+
"@vitejs/plugin-react": "^4.3.1",
22+
"typescript": "5.4.5",
23+
"vite": "^5.3.2"
24+
}
25+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
html {
2+
font-family: sans-serif;
3+
font-size: 14px;
4+
}
5+
6+
table {
7+
border: 1px solid lightgray;
8+
}
9+
10+
tbody {
11+
border-bottom: 1px solid lightgray;
12+
}
13+
14+
th {
15+
border-bottom: 1px solid lightgray;
16+
border-right: 1px solid lightgray;
17+
padding: 2px 4px;
18+
}
19+
20+
tfoot {
21+
color: gray;
22+
}
23+
24+
tfoot th {
25+
font-weight: normal;
26+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import * as React from 'react'
2+
import ReactDOM from 'react-dom/client'
3+
import { createTableHelper, flexRender } from '@tanstack/react-table'
4+
import './index.css'
5+
6+
// This example uses the new `createTableHelper` method to create a re-usable table helper object instead of independently using the standalone `useTable` hook and `createColumnHelper` method. You can choose to use either way.
7+
8+
// 1. Define what the shape of your data will be for each row
9+
type Person = {
10+
firstName: string
11+
lastName: string
12+
age: number
13+
visits: number
14+
status: string
15+
progress: number
16+
}
17+
18+
// 2. Create some dummy data with a stable reference (this could be an API response stored in useState or similar)
19+
const defaultData: Array<Person> = [
20+
{
21+
firstName: 'tanner',
22+
lastName: 'linsley',
23+
age: 24,
24+
visits: 100,
25+
status: 'In Relationship',
26+
progress: 50,
27+
},
28+
{
29+
firstName: 'tandy',
30+
lastName: 'miller',
31+
age: 40,
32+
visits: 40,
33+
status: 'Single',
34+
progress: 80,
35+
},
36+
{
37+
firstName: 'joe',
38+
lastName: 'dirte',
39+
age: 45,
40+
visits: 20,
41+
status: 'Complicated',
42+
progress: 10,
43+
},
44+
{
45+
firstName: 'kevin',
46+
lastName: 'vandy',
47+
age: 12,
48+
visits: 100,
49+
status: 'Single',
50+
progress: 70,
51+
},
52+
]
53+
54+
// 3. New in V9! Tell the table which features and row models we want to use. In this case, this will be a basic table with no additional features
55+
const tableHelper = createTableHelper({
56+
_features: {},
57+
_rowModels: {}, // `Core` row model is now included by default, but you can still override it here
58+
TData: {} as Person,
59+
})
60+
61+
// 4. Create a helper object to help define our columns
62+
const { columnHelper } = tableHelper
63+
64+
// 5. Define the columns for your table with a stable reference (in this case, defined statically outside of a react component)
65+
const columns = [
66+
// accessorKey method (most common for simple use-cases)
67+
columnHelper.accessor('firstName', {
68+
cell: (info) => info.getValue(),
69+
footer: (info) => info.column.id,
70+
}),
71+
// accessorFn used (alternative) along with a custom id
72+
columnHelper.accessor((row) => row.lastName, {
73+
id: 'lastName',
74+
cell: (info) => <i>{info.getValue()}</i>,
75+
header: () => <span>Last Name</span>,
76+
footer: (info) => info.column.id,
77+
}),
78+
// accessorFn used to transform the data
79+
columnHelper.accessor((row) => Number(row.age), {
80+
id: 'age',
81+
header: () => 'Age',
82+
cell: (info) => info.renderValue(),
83+
footer: (info) => info.column.id,
84+
}),
85+
columnHelper.accessor('visits', {
86+
header: () => <span>Visits</span>,
87+
footer: (info) => info.column.id,
88+
}),
89+
columnHelper.accessor('status', {
90+
header: 'Status',
91+
footer: (info) => info.column.id,
92+
}),
93+
columnHelper.accessor('progress', {
94+
header: 'Profile Progress',
95+
footer: (info) => info.column.id,
96+
}),
97+
]
98+
99+
function App() {
100+
// 6. Store data with a stable reference
101+
const [data, _setData] = React.useState(() => [...defaultData])
102+
const rerender = React.useReducer(() => ({}), {})[1]
103+
104+
// 7. Create the table instance with the required columns and data.
105+
// Features and row models are already defined in the table helper object above
106+
const table = tableHelper.useTable({
107+
columns,
108+
data,
109+
// add additional table options here or in the table helper above
110+
})
111+
112+
// 8. Render your table markup from the table instance APIs
113+
return (
114+
<div className="p-2">
115+
<table>
116+
<thead>
117+
{table.getHeaderGroups().map((headerGroup) => (
118+
<tr key={headerGroup.id}>
119+
{headerGroup.headers.map((header) => (
120+
<th key={header.id}>
121+
{header.isPlaceholder
122+
? null
123+
: flexRender(
124+
header.column.columnDef.header,
125+
header.getContext(),
126+
)}
127+
</th>
128+
))}
129+
</tr>
130+
))}
131+
</thead>
132+
<tbody>
133+
{table.getRowModel().rows.map((row) => (
134+
<tr key={row.id}>
135+
{row.getAllCells().map((cell) => (
136+
<td key={cell.id}>
137+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
138+
</td>
139+
))}
140+
</tr>
141+
))}
142+
</tbody>
143+
<tfoot>
144+
{table.getFooterGroups().map((footerGroup) => (
145+
<tr key={footerGroup.id}>
146+
{footerGroup.headers.map((header) => (
147+
<th key={header.id}>
148+
{header.isPlaceholder
149+
? null
150+
: flexRender(
151+
header.column.columnDef.footer,
152+
header.getContext(),
153+
)}
154+
</th>
155+
))}
156+
</tr>
157+
))}
158+
</tfoot>
159+
</table>
160+
<div className="h-4" />
161+
<button onClick={() => rerender()} className="border p-2">
162+
Rerender
163+
</button>
164+
</div>
165+
)
166+
}
167+
168+
const rootElement = document.getElementById('root')
169+
if (!rootElement) throw new Error('Failed to find the root element')
170+
171+
ReactDOM.createRoot(rootElement).render(
172+
<React.StrictMode>
173+
<App />
174+
</React.StrictMode>,
175+
)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"useDefineForClassFields": true,
5+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
6+
"module": "ESNext",
7+
"skipLibCheck": true,
8+
9+
/* Bundler mode */
10+
"moduleResolution": "bundler",
11+
"allowImportingTsExtensions": true,
12+
"resolveJsonModule": true,
13+
"isolatedModules": true,
14+
"noEmit": true,
15+
"jsx": "react-jsx",
16+
17+
/* Linting */
18+
"strict": true,
19+
"noUnusedLocals": true,
20+
"noUnusedParameters": true,
21+
"noFallthroughCasesInSwitch": true
22+
},
23+
"include": ["src"]
24+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { defineConfig } from 'vite'
2+
import react from '@vitejs/plugin-react'
3+
import rollupReplace from '@rollup/plugin-replace'
4+
5+
// https://vitejs.dev/config/
6+
export default defineConfig({
7+
plugins: [
8+
rollupReplace({
9+
preventAssignment: true,
10+
values: {
11+
__DEV__: JSON.stringify(true),
12+
'process.env.NODE_ENV': JSON.stringify('development'),
13+
},
14+
}),
15+
react(),
16+
],
17+
})

examples/react/basic/src/main.tsx

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import * as React from 'react'
22
import ReactDOM from 'react-dom/client'
3-
4-
import './index.css'
5-
63
import {
74
createColumnHelper,
8-
createCoreRowModel,
95
flexRender,
6+
tableFeatures,
107
useTable,
118
} from '@tanstack/react-table'
9+
import './index.css'
10+
11+
// This example uses the standalone `useTable` hook to create a table without the new `createTableHelper`. You can choose to use either way.
1212

13+
// 1. Define what the shape of your data will be for each row
1314
type Person = {
1415
firstName: string
1516
lastName: string
@@ -19,6 +20,7 @@ type Person = {
1920
progress: number
2021
}
2122

23+
// 2. Create some dummy data with a stable reference (this could be an API response stored in useState or similar)
2224
const defaultData: Array<Person> = [
2325
{
2426
firstName: 'tanner',
@@ -44,22 +46,40 @@ const defaultData: Array<Person> = [
4446
status: 'Complicated',
4547
progress: 10,
4648
},
49+
{
50+
firstName: 'kevin',
51+
lastName: 'vandy',
52+
age: 12,
53+
visits: 100,
54+
status: 'Single',
55+
progress: 70,
56+
},
4757
]
4858

49-
const columnHelper = createColumnHelper<any, Person>()
59+
// 3. New in V9! Tell the table which features and row models we want to use. In this case, this will be a basic table with no additional features
60+
const _features = tableFeatures({}) //util method to create sharable TFeatures object/type
61+
62+
// 4. Optionally, create a helper object to help define our columns with slightly better type inference for each column (TValue generic)
63+
const columnHelper = createColumnHelper<typeof _features, Person>()
5064

65+
// 5. Define the columns for your table
66+
// (Instead of columnHelper, you could just give this array a type of `ColumnDef<typeof _features, Person>[]`)
5167
const columns = [
68+
// accessorKey method (most common for simple use-cases)
5269
columnHelper.accessor('firstName', {
5370
cell: (info) => info.getValue(),
5471
footer: (info) => info.column.id,
5572
}),
73+
// accessorFn used (alternative) along with a custom id
5674
columnHelper.accessor((row) => row.lastName, {
5775
id: 'lastName',
5876
cell: (info) => <i>{info.getValue()}</i>,
5977
header: () => <span>Last Name</span>,
6078
footer: (info) => info.column.id,
6179
}),
62-
columnHelper.accessor('age', {
80+
// accessorFn used to transform the data
81+
columnHelper.accessor((row) => Number(row.age), {
82+
id: 'age',
6383
header: () => 'Age',
6484
cell: (info) => info.renderValue(),
6585
footer: (info) => info.column.id,
@@ -79,18 +99,20 @@ const columns = [
7999
]
80100

81101
function App() {
102+
// 6. Store data with a stable reference
82103
const [data, _setData] = React.useState(() => [...defaultData])
83104
const rerender = React.useReducer(() => ({}), {})[1]
84105

106+
// 7. Create the table instance with required _features, columns, and data
85107
const table = useTable({
86-
_features: {},
87-
_rowModels: {
88-
Core: createCoreRowModel(),
89-
},
108+
_features, // new required option in V9. Tell the table which features you are importing and using (better tree-shaking)
109+
_rowModels: {}, // `Core` row model is now included by default, but you can still override it here
90110
columns,
91111
data,
112+
// add additional table options here
92113
})
93114

115+
// 8. Render your table markup from the table instance APIs
94116
return (
95117
<div className="p-2">
96118
<table>

0 commit comments

Comments
 (0)