von Tanner Linsley am 03. Juni 2025. 
Suchparameter wurden historisch wie zweitklassiger Zustand behandelt. Sie sind global, serialisierbar und teilbar — aber in den meisten Apps werden sie immer noch mit Zeichenketten-Parsing, lockeren Konventionen und brüchigen Hilfsmitteln zusammengebastelt.
Selbst etwas einfaches, wie die Validierung eines sortieren-Parameters, wird schnell ausführlich
const schema = z.object({
sort: z.enum(['asc', 'desc']),
})
const raw = Object.fromEntries(new URLSearchParams(location.href))
const result = schema.safeParse(raw)
if (!result.success) {
// fallback, redirect, or show error
}
const schema = z.object({
sort: z.enum(['asc', 'desc']),
})
const raw = Object.fromEntries(new URLSearchParams(location.href))
const result = schema.safeParse(raw)
if (!result.success) {
// fallback, redirect, or show error
}
Das funktioniert, ist aber manuell und repetitiv. Es gibt keine Inferenz, keine Verbindung zur eigentlichen Route und es bricht zusammen, sobald Sie mehr Typen, Standardwerte, Transformationen oder Struktur hinzufügen möchten.
Noch schlimmer, URLSearchParams ist nur Zeichenkette. Es unterstützt keine verschachtelten JSONs, Arrays (über einfaches Aufteilen nach Komma hinaus) oder Typumwandlung. Wenn Ihr Zustand also nicht flach und einfach ist, stoßen Sie schnell an Grenzen.
Deshalb sehen wir einen Anstieg von Tools und Vorschlägen — Dinge wie Nuqs, Next.js RFCs und Userland-Patterns — die darauf abzielen, Suchparameter typsicherer und ergonomischer zu machen. Die meisten davon konzentrieren sich auf die Verbesserung des Lesens aus der URL.
Aber fast keiner davon löst das tiefere, schwierigere Problem: Suchparameter sicher und atomar schreiben, mit vollem Bewusstsein für den Routing-Kontext.
Es ist eine Sache, aus der URL zu lesen. Eine andere ist es, eine gültige, absichtsvolle URL aus Code zu konstruieren.
In dem Moment, in dem Sie versuchen, dies zu tun
<Link to="/dashboards/overview" search={{ sort: 'asc' }} />
<Link to="/dashboards/overview" search={{ sort: 'asc' }} />
Stellen Sie fest, dass Sie keine Ahnung haben, welche Suchparameter für diese Route gültig sind oder ob Sie sie korrekt formatieren. Selbst mit einer Hilfsfunktion zum Stringifizieren erzwingt nichts Verträge zwischen dem Aufrufer und der Route. Es gibt keine Typinferenz, keine Validierung und keine Leitplanken.
Hier wird Beschränkung zu einem Merkmal.
Ohne explizit Suchparameter-Schemata in der Route selbst zu deklarieren, sind Sie auf Raten angewiesen. Sie können an einer Stelle validieren, aber nichts hindert eine andere Komponente daran, mit ungültigem, unvollständigem oder widersprüchlichem Zustand zu navigieren.
Beschränkung ist das, was Koordination ermöglicht. Es ist das, was es nicht-lokalen Aufrufern erlaubt, sicher teilzunehmen.
Tools wie Nuqs sind ein großartiges Beispiel dafür, wie lokale Abstraktionen die Ergonomie der Suchparameter-Handhabung verbessern können. Sie erhalten Zod-basierte Parsing, Typinferenz, sogar schreibbare APIs — alles auf eine bestimmte Komponente oder Hook beschränkt.
Sie machen es einfacher, Suchparameter isoliert zu lesen und zu schreiben — und das ist wertvoll.
Aber sie lösen nicht das umfassendere Problem der Koordination. Sie landen immer noch bei duplizierten Schemata, uneinheitlichen Erwartungen und keinem Weg, die Konsistenz zwischen Routen oder Komponenten zu erzwingen. Standardwerte können widersprüchlich sein. Typen können abdriften. Und wenn sich Routen entwickeln, garantiert nichts, dass alle Aufrufer mit ihnen aktualisiert werden.
Das ist das eigentliche Fragmentierungsproblem — und seine Lösung erfordert, Suchparameter-Schemata in die Routing-Schicht selbst zu bringen.
TanStack Router löst dies ganzheitlich.
Anstatt Logik für Schemata in Ihrer App zu verteilen, definieren Sie sie innerhalb der Route selbst
export const Route = createFileRoute('/dashboards/overview')({
validateSearch: z.object({
sort: z.enum(['asc', 'desc']),
filter: z.string().optional(),
}),
})
export const Route = createFileRoute('/dashboards/overview')({
validateSearch: z.object({
sort: z.enum(['asc', 'desc']),
filter: z.string().optional(),
}),
})
Dieses Schema wird zur einzigen Wahrheitsquelle. Sie erhalten vollständige Inferenz, Validierung und Autovervollständigung überall
<Link
to="/dashboards/overview"
search={{ sort: 'asc' }} // fully typed, fully validated
/>
<Link
to="/dashboards/overview"
search={{ sort: 'asc' }} // fully typed, fully validated
/>
Möchten Sie nur einen Teil des Suchzustands aktualisieren? Kein Problem
navigate({
search: (prev) => ({ ...prev, page: prev.page + 1 }),
})
navigate({
search: (prev) => ({ ...prev, page: prev.page + 1 }),
})
Es ist reduzierer-artig, transaktional und integriert sich direkt in das Reaktionsmodell des Routers. Komponenten rendern nur neu, wenn sich der spezifische Suchparameter, den sie verwenden, ändert — nicht jedes Mal, wenn sich die URL ändert.
Wenn sich Ihre Suchparameter-Logik im Userland befindet — verstreut über Hooks, Utilities und Helfer — ist es nur eine Frage der Zeit, bis Sie auf widersprüchliche Schemata stoßen.
Vielleicht erwartet eine Komponente `sort: 'asc' | 'desc'`. Eine andere fügt einen `filter` hinzu. Eine dritte geht davon aus, dass `sort: 'desc'` standardmäßig gilt. Keiner von ihnen teilt eine Wahrheitsquelle.
Das führt zu
TanStack Router verhindert dies, indem Schemata direkt mit Ihren Routendefinitionen verknüpft werden — hierarchisch.
Elternrouten können eine gemeinsame Suchparameter-Validierung definieren. Kindrouten erben diesen Kontext, fügen ihn hinzu oder erweitern ihn auf typsichere Weise. Dies macht es unmöglich, versehentlich überlappende, inkompatible Schemata in verschiedenen Teilen Ihrer App zu erstellen.
So funktioniert das in der Praxis
// routes/dashboard.tsx
export const Route = createFileRoute('/dashboard')({
validateSearch: z.object({
sort: z.enum(['asc', 'desc']).default('asc'),
}),
})
// routes/dashboard.tsx
export const Route = createFileRoute('/dashboard')({
validateSearch: z.object({
sort: z.enum(['asc', 'desc']).default('asc'),
}),
})
Dann kann eine Kindroute das Schema sicher erweitern
// routes/dashboard/$dashboardId.tsx
export const Route = createFileRoute('/dashboard/$dashboardId')({
validateSearch: z.object({
filter: z.string().optional(),
// ✅ \`sort\` is inherited automatically from the parent
}),
})
// routes/dashboard/$dashboardId.tsx
export const Route = createFileRoute('/dashboard/$dashboardId')({
validateSearch: z.object({
filter: z.string().optional(),
// ✅ \`sort\` is inherited automatically from the parent
}),
})
Wenn Sie `/dashboard/123?sort=desc&filter=active` abgleichen, validiert die Elternroute `sort`, die Kindroute validiert `filter` und alles funktioniert nahtlos zusammen.
Versuchen Sie, den erforderlichen Elternparameter in der Kindroute auf etwas völlig anderes neu zu definieren? Typfehler.
validateSearch: z.object({
// ❌ Type error: boolean does not extend 'asc' | 'desc' from parent
sort: z.boolean(),
filter: z.string().optional(),
})
validateSearch: z.object({
// ❌ Type error: boolean does not extend 'asc' | 'desc' from parent
sort: z.boolean(),
filter: z.string().optional(),
})
Diese Art der Durchsetzung macht verschachtelte Routen komponierbar und sicher — eine seltene Kombination.
Die Magie hier ist, dass Sie Ihrem Team keine Konventionen beibringen müssen. Die Route besitzt das Schema. Jeder nutzt es einfach. Es gibt keine Duplikation. Kein Abdriften. Keine stillen Fehler. Kein Rätselraten.
Wenn Sie Validierung, Typisierung und Besitz in den Router selbst bringen, hören Sie auf, URLs als Zeichenketten zu behandeln, und beginnen Sie, sie wie echten Zustand zu behandeln — denn das sind sie.
Die meisten Routing-Systeme behandeln Suchparameter wie eine nachträgliche Überlegung. Etwas, das man lesen, vielleicht parsen, vielleicht stringifizieren kann, aber selten etwas, dem man tatsächlich vertrauen kann.
TanStack Router kehrt das um. Er macht Suchparameter zu einem Kernbestandteil des Routing-Vertrags — validiert, inferierbar, schreibbar und reaktiv.
Denn wenn Sie Suchparameter nicht wie Zustand behandeln, werden Sie sie weiterhin durchsickern lassen, kaputt machen und um sie herumarbeiten.
Besser, es von Anfang an richtig zu machen.
Wenn Sie von den Möglichkeiten, Suchparameter als erstklassigen Zustand zu behandeln, fasziniert sind, laden wir Sie ein, TanStack Router auszuprobieren. Erleben Sie die Leistungsfähigkeit von validierten, inferierbaren und reaktiven Suchparametern in Ihrer Routing-Logik.