Tabellen beginnen mit Ihren Daten. Ihre Spaltendefinitionen und Zeilen hängen von der Struktur Ihrer Daten ab. TanStack Table bietet einige TypeScript-Funktionen, die Ihnen helfen, den Rest Ihres Tabellencodes mit einer großartigen typsicheren Erfahrung zu erstellen. Wenn Sie Ihre Daten und Typen korrekt einrichten, kann TanStack Table die Struktur Ihrer Daten ableiten und sicherstellen, dass Ihre Spaltendefinitionen korrekt sind.
TypeScript ist NICHT erforderlich, um die TanStack Table-Pakete zu verwenden... ABER TanStack Table ist so geschrieben und organisiert, dass die großartige TypeScript-Erfahrung, die Sie erhalten, wie eines der Hauptverkaufsargumente der Bibliothek wirkt. Wenn Sie kein TypeScript verwenden, verpassen Sie viele großartige Autovervollständigungs- und Typprüfungsfunktionen, die sowohl Ihre Entwicklungszeit beschleunigen als auch die Anzahl der Fehler in Ihrem Code reduzieren.
Ein grundlegendes Verständnis von TypeScript Generics und deren Funktionsweise hilft Ihnen, diesen Leitfaden besser zu verstehen, aber es sollte einfach genug sein, es unterwegs zu lernen. Die offizielle TypeScript Generics Docs kann für diejenigen hilfreich sein, die mit TypeScript noch nicht vertraut sind.
Die data ist ein Array von Objekten, die in die Zeilen Ihrer Tabelle umgewandelt werden. Jedes Objekt im Array repräsentiert eine Datenzeile (unter normalen Umständen). Wenn Sie TypeScript verwenden, definieren wir normalerweise einen Typ für die Struktur unserer Daten. Dieser Typ wird als generischer Typ für alle anderen Tabellen-, Spalten-, Zeilen- und Zellinstanzen verwendet. Dieses Generic wird im Rest der TanStack Table-Typen und APIs normalerweise als TData bezeichnet.
Wenn wir zum Beispiel eine Tabelle haben, die eine Liste von Benutzern in einem Array wie diesem anzeigt
[
{
"firstName": "Tanner",
"lastName": "Linsley",
"age": 33,
"visits": 100,
"progress": 50,
"status": "Married"
},
{
"firstName": "Kevin",
"lastName": "Vandy",
"age": 27,
"visits": 200,
"progress": 100,
"status": "Single"
}
]
[
{
"firstName": "Tanner",
"lastName": "Linsley",
"age": 33,
"visits": 100,
"progress": 50,
"status": "Married"
},
{
"firstName": "Kevin",
"lastName": "Vandy",
"age": 27,
"visits": 200,
"progress": 100,
"status": "Single"
}
]
Dann können wir einen User (TData) Typ wie diesen definieren
//TData
type User = {
firstName: string
lastName: string
age: number
visits: number
progress: number
status: string
}
//TData
type User = {
firstName: string
lastName: string
age: number
visits: number
progress: number
status: string
}
Wir können dann unser data-Array mit diesem Typ definieren, und TanStack Table kann dann später viele Typen für uns in unseren Spalten, Zeilen, Zellen usw. intelligent ableiten. Dies liegt daran, dass der data-Typ buchstäblich als TData-Generictyp definiert ist. Alles, was Sie an die data-Tabellenoption übergeben, wird zum TData-Typ für den Rest der Tabelleninstanz. Stellen Sie einfach sicher, dass Ihre Spaltendefinitionen denselben TData-Typ wie der data-Typ verwenden, wenn Sie sie später definieren.
//note: data needs a "stable" reference in order to prevent infinite re-renders
const data: User[] = []
//or
const [data, setData] = React.useState<User[]>([])
//or
const data = ref<User[]>([]) //vue
//etc...
//note: data needs a "stable" reference in order to prevent infinite re-renders
const data: User[] = []
//or
const [data, setData] = React.useState<User[]>([])
//or
const data = ref<User[]>([]) //vue
//etc...
Wenn Ihre Daten kein schönes flaches Array von Objekten sind, ist das in Ordnung! Sobald Sie mit der Definition Ihrer Spalten beginnen, gibt es Strategien, um auf tief verschachtelte Daten in Ihren Accessoren zuzugreifen.
Wenn Ihre data so aussieht
[
{
"name": {
"first": "Tanner",
"last": "Linsley"
},
"info": {
"age": 33,
"visits": 100,
}
},
{
"name": {
"first": "Kevin",
"last": "Vandy"
},
"info": {
"age": 27,
"visits": 200,
}
}
]
[
{
"name": {
"first": "Tanner",
"last": "Linsley"
},
"info": {
"age": 33,
"visits": 100,
}
},
{
"name": {
"first": "Kevin",
"last": "Vandy"
},
"info": {
"age": 27,
"visits": 200,
}
}
]
Sie können einen Typ wie diesen definieren
type User = {
name: {
first: string
last: string
}
info: {
age: number
visits: number
}
}
type User = {
name: {
first: string
last: string
}
info: {
age: number
visits: number
}
}
Und Sie können auf die Daten in Ihren Spaltendefinitionen entweder mit Punktnotation in einem accessorKey oder einfach durch die Verwendung eines accessorFn zugreifen.
const columns = [
{
header: 'First Name',
accessorKey: 'name.first',
},
{
header: 'Last Name',
accessorKey: 'name.last',
},
{
header: 'Age',
accessorFn: row => row.info.age,
},
//...
]
const columns = [
{
header: 'First Name',
accessorKey: 'name.first',
},
{
header: 'Last Name',
accessorKey: 'name.last',
},
{
header: 'Age',
accessorFn: row => row.info.age,
},
//...
]
Dies wird im Leitfaden zu Spaltendefinitionen detaillierter erläutert.
HINWEIS: Die "Schlüssel" in Ihren JSON-Daten können normalerweise alles sein, aber alle Punkte in den Schlüsseln werden als tief verschachtelter Schlüssel interpretiert und verursachen Fehler.
Wenn Sie erweiterbare Funktionen verwenden, kann es üblich sein, verschachtelte Unterzeilen in Ihren Daten zu haben. Dies führt zu einem rekursiven Typ, der etwas anders ist.
Wenn Ihre Daten also so aussehen
[
{
"firstName": "Tanner",
"lastName": "Linsley",
"subRows": [
{
"firstName": "Kevin",
"lastName": "Vandy",
},
{
"firstName": "John",
"lastName": "Doe",
"subRows": [
//...
]
}
]
},
{
"firstName": "Jane",
"lastName": "Doe",
}
]
[
{
"firstName": "Tanner",
"lastName": "Linsley",
"subRows": [
{
"firstName": "Kevin",
"lastName": "Vandy",
},
{
"firstName": "John",
"lastName": "Doe",
"subRows": [
//...
]
}
]
},
{
"firstName": "Jane",
"lastName": "Doe",
}
]
Sie können einen Typ wie diesen definieren
type User = {
firstName: string
lastName: string
subRows?: User[] //does not have to be called "subRows", can be called anything
}
type User = {
firstName: string
lastName: string
subRows?: User[] //does not have to be called "subRows", can be called anything
}
Wo subRows ein optionales Array von User-Objekten ist. Dies wird im Erweiterungsleitfaden detaillierter erläutert.
Das data-Array, das Sie an die Tabelleninstanz übergeben, MUSS einen "stabilen" Verweis haben, um Fehler zu vermeiden, die zu endlosen Neuberechnungen führen (insbesondere in React).
Dies hängt vom verwendeten Framework-Adapter ab, aber in React sollten Sie oft React.useState, React.useMemo oder ähnliches verwenden, um sicherzustellen, dass sowohl die data- als auch die columns-Tabellenoptionen stabile Verweise haben.
const fallbackData = []
export default function MyComponent() {
//✅ GOOD: This will not cause an infinite loop of re-renders because `columns` is a stable reference
const columns = useMemo(() => [
// ...
], []);
//✅ GOOD: This will not cause an infinite loop of re-renders because `data` is a stable reference
const [data, setData] = useState(() => [
// ...
]);
// Columns and data are defined in a stable reference, will not cause infinite loop!
const table = useReactTable({
columns,
data ?? fallbackData, //also good to use a fallback array that is defined outside of the component (stable reference)
});
return <table>...</table>;
}
const fallbackData = []
export default function MyComponent() {
//✅ GOOD: This will not cause an infinite loop of re-renders because `columns` is a stable reference
const columns = useMemo(() => [
// ...
], []);
//✅ GOOD: This will not cause an infinite loop of re-renders because `data` is a stable reference
const [data, setData] = useState(() => [
// ...
]);
// Columns and data are defined in a stable reference, will not cause infinite loop!
const table = useReactTable({
columns,
data ?? fallbackData, //also good to use a fallback array that is defined outside of the component (stable reference)
});
return <table>...</table>;
}
React.useState und React.useMemo sind nicht die einzigen Möglichkeiten, Ihren Daten einen stabilen Verweis zu geben. Sie können Ihre Daten auch außerhalb der Komponente definieren oder eine Drittanbieter-Zustandsmanagementbibliothek wie Redux, Zustand oder TanStack Query verwenden.
Das Wichtigste, was Sie vermeiden sollten, ist, das data-Array im selben Geltungsbereich wie den useReactTable-Aufruf zu definieren. Dadurch wird das data-Array bei jeder Neuberechnung neu definiert, was zu einer endlosen Schleife von Neuberechnungen führt.
export default function MyComponent() {
//😵 BAD: This will cause an infinite loop of re-renders because `columns` is redefined as a new array on every render!
const columns = [
// ...
];
//😵 BAD: This will cause an infinite loop of re-renders because `data` is redefined as a new array on every render!
const data = [
// ...
];
//❌ Columns and data are defined in the same scope as `useReactTable` without a stable reference, will cause infinite loop!
const table = useReactTable({
columns,
data ?? [], //❌ Also bad because the fallback array is re-created on every render
});
return <table>...</table>;
}
export default function MyComponent() {
//😵 BAD: This will cause an infinite loop of re-renders because `columns` is redefined as a new array on every render!
const columns = [
// ...
];
//😵 BAD: This will cause an infinite loop of re-renders because `data` is redefined as a new array on every render!
const data = [
// ...
];
//❌ Columns and data are defined in the same scope as `useReactTable` without a stable reference, will cause infinite loop!
const table = useReactTable({
columns,
data ?? [], //❌ Also bad because the fallback array is re-created on every render
});
return <table>...</table>;
}
Später, in anderen Teilen dieser Dokumentation, erfahren Sie, wie TanStack Table die data verarbeitet, die Sie der Tabelle übergeben, und die Zeilen- und Zellobjekte generiert, die zum Erstellen der Tabelle verwendet werden. Die data, die Sie der Tabelle übergeben, wird von TanStack Table nie verändert, aber die tatsächlichen Werte in den Zeilen und Zellen können durch die Accessoren in Ihren Spaltendefinitionen oder durch andere von Zeilenmodellen durchgeführte Funktionen wie Gruppierung oder Aggregation transformiert werden.
Glauben Sie es oder nicht, TanStack Table wurde tatsächlich entwickelt, um potenziell Hunderttausende von Datenzeilen im Client zu verarbeiten. Dies ist offensichtlich nicht immer möglich, abhängig von der Größe der Daten jeder Spalte und der Anzahl der Spalten. Die Funktionen zum Sortieren, Filtern, Paginieren und Gruppieren sind jedoch alle auf Leistung bei großen Datensätzen ausgelegt.
Die Standardeinstellung eines Entwicklers, der ein Datenraster erstellt, ist die Implementierung von serverseitigem Paginieren, Sortieren und Filtern für große Datensätze. Dies ist immer noch normalerweise eine gute Idee, aber viele Entwickler unterschätzen, wie viele Daten mit modernen Browsern und den richtigen Optimierungen tatsächlich im Client verarbeitet werden können. Wenn Ihre Tabelle niemals mehr als ein paar Tausend Zeilen haben wird, können Sie wahrscheinlich die Client-seitigen Funktionen von TanStack Table nutzen, anstatt sie selbst auf dem Server zu implementieren. Bevor Sie sich jedoch dafür entscheiden, dass die Client-seitigen Funktionen von TanStack Table Ihren großen Datensatz verarbeiten, sollten Sie ihn mit Ihren tatsächlichen Daten testen, um zu sehen, ob er für Ihre Bedürfnisse gut genug funktioniert.
Dies wird im Paginierungsleitfaden detaillierter erläutert.
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.