Is it possible to combine Tanstack Form and Tanstack Virtual ? #2062
-
|
For I want to thank the team for the latest improvements in performance in v1.28.4 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
Yes, you can combine them. The trick is to only render Here's the general approach using TanStack Virtual + TanStack Form: import { useVirtualizer } from '@tanstack/react-virtual'
import { useForm } from '@tanstack/react-form'
function VirtualizedForm() {
const form = useForm({
defaultValues: {
rows: Array.from({ length: 500 }, (_, i) => ({
name: `Item ${i}`,
quantity: 0,
price: 0,
})),
},
onSubmit: ({ value }) => console.log(value),
})
const parentRef = useRef<HTMLDivElement>(null)
const virtualizer = useVirtualizer({
count: form.state.values.rows.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50, // row height in px
overscan: 5,
})
return (
<form onSubmit={(e) => { e.preventDefault(); form.handleSubmit() }}>
<div ref={parentRef} style={{ height: 600, overflow: 'auto' }}>
<div style={{ height: virtualizer.getTotalSize(), position: 'relative' }}>
{virtualizer.getVirtualItems().map((virtualRow) => (
<div
key={virtualRow.key}
style={{
position: 'absolute',
top: virtualRow.start,
height: virtualRow.size,
width: '100%',
display: 'flex',
gap: 8,
}}
>
<form.Field name={`rows[${virtualRow.index}].name`}>
{(field) => (
<input
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
/>
)}
</form.Field>
<form.Field name={`rows[${virtualRow.index}].quantity`}>
{(field) => (
<input
type="number"
value={field.state.value}
onChange={(e) => field.handleChange(Number(e.target.value))}
/>
)}
</form.Field>
<form.Field name={`rows[${virtualRow.index}].price`}>
{(field) => (
<input
type="number"
value={field.state.value}
onChange={(e) => field.handleChange(Number(e.target.value))}
/>
)}
</form.Field>
</div>
))}
</div>
</div>
<button type="submit">Submit</button>
</form>
)
}A few things to keep in mind:
|
Beta Was this translation helpful? Give feedback.
Yes, you can combine them. The trick is to only render
<Field>components for the rows that are currently visible in the virtual window, rather than mounting all 100+ fields at once.Here's the general approach using TanStack Virtual + TanStack Form: