-
-
Notifications
You must be signed in to change notification settings - Fork 306
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(docs): Add example for using tanstack table with react with vir…
…tualized rows (#513)
- Loading branch information
1 parent
5074d52
commit 976210c
Showing
11 changed files
with
1,096 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
node_modules | ||
.DS_Store | ||
dist | ||
dist-ssr | ||
*.local |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Example | ||
|
||
To run this example: | ||
|
||
- `npm install` or `npm` | ||
- `npm run start` or `npm run start` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite App</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "tanstack-react-virtual-example-dynamic", | ||
"version": "0.0.0", | ||
"private": true, | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "vite build", | ||
"serve": "vite preview --port 3001", | ||
"start": "vite" | ||
}, | ||
"dependencies": { | ||
"@faker-js/faker": "7.6.0", | ||
"@tanstack/react-table": "^8.7.9", | ||
"@tanstack/react-virtual": "3.0.0-beta.49", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "^18.0.25", | ||
"@types/react-dom": "^18.0.8", | ||
"@vitejs/plugin-react": "^2.2.0", | ||
"vite": "^3.2.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
*, | ||
*:before, | ||
*:after { | ||
box-sizing: border-box; | ||
} | ||
|
||
html { | ||
font-family: sans-serif; | ||
font-size: 14px; | ||
} | ||
|
||
body { | ||
padding: 1rem; | ||
} | ||
|
||
.container { | ||
height: 600px; | ||
overflow: auto; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
import * as React from 'react' | ||
import { createRoot } from 'react-dom/client' | ||
|
||
import { useVirtualizer } from '@tanstack/react-virtual' | ||
import { | ||
ColumnDef, | ||
flexRender, | ||
getCoreRowModel, | ||
getSortedRowModel, | ||
Row, | ||
SortingState, | ||
useReactTable, | ||
} from '@tanstack/react-table' | ||
import { makeData, Person } from './makeData' | ||
import './index.css' | ||
|
||
function ReactTableVirtualized() { | ||
const [sorting, setSorting] = React.useState<SortingState>([]) | ||
|
||
const columns = React.useMemo<ColumnDef<Person>[]>( | ||
() => [ | ||
{ | ||
accessorKey: 'id', | ||
header: 'ID', | ||
size: 60, | ||
}, | ||
{ | ||
accessorKey: 'firstName', | ||
cell: info => info.getValue(), | ||
}, | ||
{ | ||
accessorFn: row => row.lastName, | ||
id: 'lastName', | ||
cell: info => info.getValue(), | ||
header: () => <span>Last Name</span>, | ||
}, | ||
{ | ||
accessorKey: 'age', | ||
header: () => 'Age', | ||
size: 50, | ||
}, | ||
{ | ||
accessorKey: 'visits', | ||
header: () => <span>Visits</span>, | ||
size: 50, | ||
}, | ||
{ | ||
accessorKey: 'status', | ||
header: 'Status', | ||
}, | ||
{ | ||
accessorKey: 'progress', | ||
header: 'Profile Progress', | ||
size: 80, | ||
}, | ||
{ | ||
accessorKey: 'createdAt', | ||
header: 'Created At', | ||
cell: info => info.getValue<Date>().toLocaleString(), | ||
}, | ||
], | ||
[] | ||
) | ||
|
||
const [data, setData] = React.useState(() => makeData(50_000)) | ||
|
||
const table = useReactTable({ | ||
data, | ||
columns, | ||
state: { | ||
sorting, | ||
}, | ||
onSortingChange: setSorting, | ||
getCoreRowModel: getCoreRowModel(), | ||
getSortedRowModel: getSortedRowModel(), | ||
debugTable: true, | ||
}) | ||
|
||
const {rows} = table.getRowModel(); | ||
|
||
|
||
const parentRef = React.useRef<HTMLDivElement>(null) | ||
|
||
const virtualizer = useVirtualizer({ | ||
count: rows.length, | ||
getScrollElement: () => parentRef.current, | ||
estimateSize: () => 34, | ||
overscan: 20 | ||
}); | ||
|
||
return ( | ||
<div ref={parentRef} className="container"> | ||
<div style={{ height: `${virtualizer.getTotalSize()}px`}}> | ||
<table> | ||
<thead> | ||
{table.getHeaderGroups().map(headerGroup => ( | ||
<tr key={headerGroup.id}> | ||
{headerGroup.headers.map(header => { | ||
return ( | ||
<th | ||
key={header.id} | ||
colSpan={header.colSpan} | ||
style={{ width: header.getSize() }} | ||
> | ||
{header.isPlaceholder ? null : ( | ||
<div | ||
{...{ | ||
className: header.column.getCanSort() | ||
? 'cursor-pointer select-none' | ||
: '', | ||
onClick: header.column.getToggleSortingHandler(), | ||
}} | ||
> | ||
{flexRender( | ||
header.column.columnDef.header, | ||
header.getContext() | ||
)} | ||
{{ | ||
asc: ' 🔼', | ||
desc: ' 🔽', | ||
}[header.column.getIsSorted() as string] ?? null} | ||
</div> | ||
)} | ||
</th> | ||
) | ||
})} | ||
</tr> | ||
))} | ||
</thead> | ||
<tbody> | ||
{virtualizer.getVirtualItems().map((virtualRow, index) => { | ||
const row = rows[virtualRow.index] as Row<Person> | ||
return ( | ||
<tr key={row.id} | ||
style={{ | ||
height: `${virtualRow.size}px`, | ||
transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`, | ||
}}> | ||
{row.getVisibleCells().map(cell => { | ||
return ( | ||
<td key={cell.id}> | ||
{flexRender( | ||
cell.column.columnDef.cell, | ||
cell.getContext() | ||
)} | ||
</td> | ||
) | ||
})} | ||
</tr> | ||
) | ||
})} | ||
</tbody> | ||
</table> | ||
</div></div> | ||
) | ||
} | ||
|
||
function App() { | ||
return ( | ||
<div> | ||
<p> | ||
For tables, the basis for the offset of the translate css function is from the row's initial position itself. Because of this, we need to calculate the translateY pixel count different and base it off the the index. | ||
</p> | ||
<ReactTableVirtualized /> | ||
<br /> | ||
<br /> | ||
{process.env.NODE_ENV === 'development' ? ( | ||
<p> | ||
<strong>Notice:</strong> You are currently running React in | ||
development mode. Rendering performance will be slightly degraded | ||
until this application is build for production. | ||
</p> | ||
) : null} | ||
</div> | ||
) | ||
} | ||
|
||
const container = document.getElementById('root') | ||
const root = createRoot(container!) | ||
const { StrictMode } = React | ||
|
||
root.render( | ||
<StrictMode> | ||
<App /> | ||
</StrictMode>, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { faker } from '@faker-js/faker' | ||
|
||
export type Person = { | ||
id: number | ||
firstName: string | ||
lastName: string | ||
age: number | ||
visits: number | ||
progress: number | ||
status: 'relationship' | 'complicated' | 'single' | ||
createdAt: Date | ||
} | ||
|
||
const range = (len: number) => { | ||
const arr: number[] = [] | ||
for (let i = 0; i < len; i++) { | ||
arr.push(i) | ||
} | ||
return arr | ||
} | ||
|
||
const newPerson = (index: number): Person => { | ||
return { | ||
id: index + 1, | ||
firstName: faker.name.firstName(), | ||
lastName: faker.name.lastName(), | ||
age: faker.datatype.number(40), | ||
visits: faker.datatype.number(1000), | ||
progress: faker.datatype.number(100), | ||
createdAt: faker.datatype.datetime({ max: new Date().getTime() }), | ||
status: faker.helpers.shuffle<Person['status']>([ | ||
'relationship', | ||
'complicated', | ||
'single', | ||
])[0]!, | ||
} | ||
} | ||
|
||
export function makeData(...lens: number[]) { | ||
const makeDataLevel = (depth = 0): Person[] => { | ||
const len = lens[depth]! | ||
return range(len).map((d): Person => { | ||
return { | ||
...newPerson(d), | ||
} | ||
}) | ||
} | ||
|
||
return makeDataLevel() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"composite": true, | ||
"extends": "../../../tsconfig.base.json", | ||
"compilerOptions": { | ||
"outDir": "./build/types" | ||
}, | ||
"files": ["src/main.tsx"], | ||
"include": [ | ||
"src" | ||
// "__tests__/**/*.test.*" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { defineConfig } from 'vite' | ||
import react from '@vitejs/plugin-react' | ||
|
||
// https://vitejs.dev/config/ | ||
export default defineConfig({ | ||
plugins: [react()] | ||
}) |
Oops, something went wrong.