ToOptions SchnittstelleNavigateOptions SchnittstelleLinkOptions Schnittstelle<Link> Komponente"." und ".."active & inactive Propsdata-status AttributisActive an KinderuseNavigatenavigate OptionenNavigate Komponenterouter.navigateuseMatchRoute und <MatchRoute>Glauben Sie es oder nicht, jede Navigation innerhalb einer App ist relativ, auch wenn Sie keine explizite relative Pfadsyntax verwenden (../../somewhere). Jedes Mal, wenn ein Link angeklickt wird oder ein imperativer Navigationsaufruf erfolgt, haben Sie immer einen Ursprungspfad und einen Zielpfad, was bedeutet, dass Sie von einer Route zu einer anderen navigieren.
TanStack Router berücksichtigt dieses konstante Konzept der relativen Navigation für jede Navigation. Daher werden Sie in der API ständig zwei Eigenschaften sehen:
⚠️ Wenn kein from Routenpfad angegeben ist, geht der Router davon aus, dass Sie von der Root-Route / navigieren und vervollständigt nur absolute Pfade. Schließlich müssen Sie wissen, woher Sie kommen, um zu wissen, wohin Sie gehen 😉.
Jede Navigations- und Routenabgleich-API in TanStack Router verwendet dieselbe Kernschnittstelle mit geringfügigen Unterschieden, abhängig von der API. Das bedeutet, dass Sie Navigation und Routenabgleich einmal lernen und die gleiche Syntax und Konzepte in der gesamten Bibliothek verwenden können.
Dies ist die Kern-Schnittstelle ToOptions, die in jeder Navigations- und Routenabgleich-API verwendet wird.
type ToOptions<
TRouteTree extends AnyRoute = AnyRoute,
TFrom extends RoutePaths<TRouteTree> | string = string,
TTo extends string = '',
> = {
// `from` is an optional route ID or path. If it is not supplied, only absolute paths will be auto-completed and type-safe. It's common to supply the route.fullPath of the origin route you are rendering from for convenience. If you don't know the origin route, leave this empty and work with absolute paths or unsafe relative paths.
from?: string
// `to` can be an absolute route path or a relative path from the `from` option to a valid route path. ⚠️ Do not interpolate path params, hash or search params into the `to` options. Use the `params`, `search`, and `hash` options instead.
to: string
// `params` is either an object of path params to interpolate into the `to` option or a function that supplies the previous params and allows you to return new ones. This is the only way to interpolate dynamic parameters into the final URL. Depending on the `from` and `to` route, you may need to supply none, some or all of the path params. TypeScript will notify you of the required params if there are any.
params:
| Record<string, unknown>
| ((prevParams: Record<string, unknown>) => Record<string, unknown>)
// `search` is either an object of query params or a function that supplies the previous search and allows you to return new ones. Depending on the `from` and `to` route, you may need to supply none, some or all of the query params. TypeScript will notify you of the required search params if there are any.
search:
| Record<string, unknown>
| ((prevSearch: Record<string, unknown>) => Record<string, unknown>)
// `hash` is either a string or a function that supplies the previous hash and allows you to return a new one.
hash?: string | ((prevHash: string) => string)
// `state` is either an object of state or a function that supplies the previous state and allows you to return a new one. State is stored in the history API and can be useful for passing data between routes that you do not want to permanently store in URL search params.
state?:
| Record<string, any>
| ((prevState: Record<string, unknown>) => Record<string, unknown>)
}
type ToOptions<
TRouteTree extends AnyRoute = AnyRoute,
TFrom extends RoutePaths<TRouteTree> | string = string,
TTo extends string = '',
> = {
// `from` is an optional route ID or path. If it is not supplied, only absolute paths will be auto-completed and type-safe. It's common to supply the route.fullPath of the origin route you are rendering from for convenience. If you don't know the origin route, leave this empty and work with absolute paths or unsafe relative paths.
from?: string
// `to` can be an absolute route path or a relative path from the `from` option to a valid route path. ⚠️ Do not interpolate path params, hash or search params into the `to` options. Use the `params`, `search`, and `hash` options instead.
to: string
// `params` is either an object of path params to interpolate into the `to` option or a function that supplies the previous params and allows you to return new ones. This is the only way to interpolate dynamic parameters into the final URL. Depending on the `from` and `to` route, you may need to supply none, some or all of the path params. TypeScript will notify you of the required params if there are any.
params:
| Record<string, unknown>
| ((prevParams: Record<string, unknown>) => Record<string, unknown>)
// `search` is either an object of query params or a function that supplies the previous search and allows you to return new ones. Depending on the `from` and `to` route, you may need to supply none, some or all of the query params. TypeScript will notify you of the required search params if there are any.
search:
| Record<string, unknown>
| ((prevSearch: Record<string, unknown>) => Record<string, unknown>)
// `hash` is either a string or a function that supplies the previous hash and allows you to return a new one.
hash?: string | ((prevHash: string) => string)
// `state` is either an object of state or a function that supplies the previous state and allows you to return a new one. State is stored in the history API and can be useful for passing data between routes that you do not want to permanently store in URL search params.
state?:
| Record<string, any>
| ((prevState: Record<string, unknown>) => Record<string, unknown>)
}
🧠 Jedes Routenobjekt hat eine to-Eigenschaft, die als to für jede Navigations- oder Routenabgleich-API verwendet werden kann. Wo immer möglich, ermöglicht Ihnen dies, reine Strings zu vermeiden und stattdessen typsichere Routenreferenzen zu verwenden.
import { Route as aboutRoute } from './routes/about.tsx'
function Comp() {
return <Link to={aboutRoute.to}>About</Link>
}
import { Route as aboutRoute } from './routes/about.tsx'
function Comp() {
return <Link to={aboutRoute.to}>About</Link>
}
Dies ist die Kern-Schnittstelle NavigateOptions, die ToOptions erweitert. Jede API, die tatsächlich eine Navigation durchführt, verwendet diese Schnittstelle.
export type NavigateOptions<
TRouteTree extends AnyRoute = AnyRoute,
TFrom extends RoutePaths<TRouteTree> | string = string,
TTo extends string = '',
> = ToOptions<TRouteTree, TFrom, TTo> & {
// `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
replace?: boolean
// `resetScroll` is a boolean that determines whether scroll position will be reset to 0,0 after the location is committed to browser history.
resetScroll?: boolean
// `hashScrollIntoView` is a boolean or object that determines whether an id matching the hash will be scrolled into view after the location is committed to history.
hashScrollIntoView?: boolean | ScrollIntoViewOptions
// `viewTransition` is either a boolean or function that determines if and how the browser will call document.startViewTransition() when navigating.
viewTransition?: boolean | ViewTransitionOptions
// `ignoreBlocker` is a boolean that determines if navigation should ignore any blockers that might prevent it.
ignoreBlocker?: boolean
// `reloadDocument` is a boolean that determines if navigation to a route inside of router will trigger a full page load instead of the traditional SPA navigation.
reloadDocument?: boolean
// `href` is a string that can be used in place of `to` to navigate to a full built href, e.g. pointing to an external target.
href?: string
}
export type NavigateOptions<
TRouteTree extends AnyRoute = AnyRoute,
TFrom extends RoutePaths<TRouteTree> | string = string,
TTo extends string = '',
> = ToOptions<TRouteTree, TFrom, TTo> & {
// `replace` is a boolean that determines whether the navigation should replace the current history entry or push a new one.
replace?: boolean
// `resetScroll` is a boolean that determines whether scroll position will be reset to 0,0 after the location is committed to browser history.
resetScroll?: boolean
// `hashScrollIntoView` is a boolean or object that determines whether an id matching the hash will be scrolled into view after the location is committed to history.
hashScrollIntoView?: boolean | ScrollIntoViewOptions
// `viewTransition` is either a boolean or function that determines if and how the browser will call document.startViewTransition() when navigating.
viewTransition?: boolean | ViewTransitionOptions
// `ignoreBlocker` is a boolean that determines if navigation should ignore any blockers that might prevent it.
ignoreBlocker?: boolean
// `reloadDocument` is a boolean that determines if navigation to a route inside of router will trigger a full page load instead of the traditional SPA navigation.
reloadDocument?: boolean
// `href` is a string that can be used in place of `to` to navigate to a full built href, e.g. pointing to an external target.
href?: string
}
Überall dort, wo ein tatsächlicher <a>-Tag verwendet wird, ist die Schnittstelle LinkOptions, die NavigateOptions erweitert, verfügbar.
export type LinkOptions<
TRouteTree extends AnyRoute = AnyRoute,
TFrom extends RoutePaths<TRouteTree> | string = string,
TTo extends string = '',
> = NavigateOptions<TRouteTree, TFrom, TTo> & {
// The standard anchor tag target attribute
target?: HTMLAnchorElement['target']
// Defaults to `{ exact: false, includeHash: false }`
activeOptions?: {
exact?: boolean
includeHash?: boolean
includeSearch?: boolean
explicitUndefined?: boolean
}
// If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
preload?: false | 'intent'
// Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
preloadDelay?: number
// If true, will render the link without the href attribute
disabled?: boolean
}
export type LinkOptions<
TRouteTree extends AnyRoute = AnyRoute,
TFrom extends RoutePaths<TRouteTree> | string = string,
TTo extends string = '',
> = NavigateOptions<TRouteTree, TFrom, TTo> & {
// The standard anchor tag target attribute
target?: HTMLAnchorElement['target']
// Defaults to `{ exact: false, includeHash: false }`
activeOptions?: {
exact?: boolean
includeHash?: boolean
includeSearch?: boolean
explicitUndefined?: boolean
}
// If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
preload?: false | 'intent'
// Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
preloadDelay?: number
// If true, will render the link without the href attribute
disabled?: boolean
}
Mit relativer Navigation und allen Schnittstellen im Hinterkopf, sprechen wir nun über die verschiedenen Navigations-APIs, die Ihnen zur Verfügung stehen.
⚠️ Keine dieser APIs ist ein Ersatz für serverseitige Weiterleitungen. Wenn Sie einen Benutzer sofort von einer Route zu einer anderen weiterleiten müssen, bevor Ihre Anwendung gemountet wird, verwenden Sie stattdessen eine serverseitige Weiterleitung anstelle einer clientseitigen Navigation.
Die Link-Komponente ist die gebräuchlichste Methode, um innerhalb einer App zu navigieren. Sie rendert ein tatsächliches <a>-Tag mit einem gültigen href-Attribut, das angeklickt oder sogar mit Cmd/Strg + Klick in einem neuen Tab geöffnet werden kann. Sie unterstützt auch alle normalen <a>-Attribute, einschließlich target, um Links in neuen Fenstern zu öffnen usw.
Zusätzlich zur Schnittstelle LinkOptions unterstützt die Link-Komponente auch die folgenden Props:
export type LinkProps<
TFrom extends RoutePaths<RegisteredRouter['routeTree']> | string = string,
TTo extends string = '',
> = LinkOptions<RegisteredRouter['routeTree'], TFrom, TTo> & {
// A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
activeProps?:
| FrameworkHTMLAnchorTagAttributes
| (() => FrameworkHTMLAnchorAttributes)
// A function that returns additional props for the `inactive` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
inactiveProps?:
| FrameworkHTMLAnchorAttributes
| (() => FrameworkHTMLAnchorAttributes)
}
export type LinkProps<
TFrom extends RoutePaths<RegisteredRouter['routeTree']> | string = string,
TTo extends string = '',
> = LinkOptions<RegisteredRouter['routeTree'], TFrom, TTo> & {
// A function that returns additional props for the `active` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
activeProps?:
| FrameworkHTMLAnchorTagAttributes
| (() => FrameworkHTMLAnchorAttributes)
// A function that returns additional props for the `inactive` state of this link. These props override other props passed to the link (`style`'s are merged, `className`'s are concatenated)
inactiveProps?:
| FrameworkHTMLAnchorAttributes
| (() => FrameworkHTMLAnchorAttributes)
}
Erstellen wir einen einfachen statischen Link!
import { Link } from '@tanstack/solid-router'
const link = <Link to="/about">About</Link>
import { Link } from '@tanstack/solid-router'
const link = <Link to="/about">About</Link>
Dynamische Links sind Links, die dynamische Segmente enthalten. Zum Beispiel könnte ein Link zu einem Blogbeitrag so aussehen:
const link = (
<Link
to="/blog/post/$postId"
params={{
postId: 'my-first-blog-post',
}}
>
Blog Post
</Link>
)
const link = (
<Link
to="/blog/post/$postId"
params={{
postId: 'my-first-blog-post',
}}
>
Blog Post
</Link>
)
Beachten Sie, dass dynamische Segmentparameter normalerweise string-Werte sind, aber sie können auch jeder andere Typ sein, zu dem Sie sie in Ihren Routenoptionen parsen. In beiden Fällen wird der Typ zur Kompilierzeit überprüft, um sicherzustellen, dass Sie den richtigen Typ übergeben.
Standardmäßig sind alle Links absolut, es sei denn, ein from-Routenpfad wird angegeben. Das bedeutet, dass der obige Link unabhängig davon, auf welcher Route Sie sich gerade befinden, immer zur Route /about navigiert.
Relative Links können mit einem from-Routenpfad kombiniert werden. Wenn kein From-Routenpfad angegeben ist, werden relative Pfade standardmäßig an den aktuellen aktiven Speicherort aufgelöst.
const postIdRoute = createRoute({
path: '/blog/post/$postId',
})
const link = (
<Link from={postIdRoute.fullPath} to="../categories">
Categories
</Link>
)
const postIdRoute = createRoute({
path: '/blog/post/$postId',
})
const link = (
<Link from={postIdRoute.fullPath} to="../categories">
Categories
</Link>
)
Wie oben gezeigt, ist es üblich, den route.fullPath als from-Routenpfad anzugeben. Dies liegt daran, dass route.fullPath eine Referenz ist, die sich aktualisiert, wenn Sie Ihre Anwendung refaktorisieren. Manchmal ist es jedoch nicht möglich, die Route direkt zu importieren. In diesem Fall ist es in Ordnung, den Routenpfad direkt als String anzugeben. Er wird weiterhin wie üblich typsicher überprüft!
Sehr oft möchten Sie den aktuellen Speicherort oder einen anderen from-Pfad neu laden, z. B. um die Loader auf der aktuellen und/oder übergeordneten Routen erneut auszuführen, oder vielleicht zu einer übergeordneten Route zurückzukehren. Dies kann erreicht werden, indem ein to-Routenpfad von "." angegeben wird, was den aktuellen Speicherort oder den angegebenen from-Pfad neu lädt.
Ein weiterer häufiger Bedarf ist die Navigation eine Route zurück relativ zum aktuellen Speicherort oder einem anderen Pfad. Durch die Angabe eines to-Routenpfads von ".." wird die Navigation zur ersten übergeordneten Route vor dem aktuellen Speicherort aufgelöst.
export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})
function PostComponent() {
return (
<div>
<Link to=".">Reload the current route of /posts/$postId</Link>
<Link to="..">Navigate back to /posts</Link>
// the below are all equivalent
<Link to="/posts">Navigate back to /posts</Link>
<Link from="/posts" to=".">
Navigate back to /posts
</Link>
// the below are all equivalent
<Link to="/">Navigate to root</Link>
<Link from="/posts" to="..">
Navigate to root
</Link>
</div>
)
}
export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})
function PostComponent() {
return (
<div>
<Link to=".">Reload the current route of /posts/$postId</Link>
<Link to="..">Navigate back to /posts</Link>
// the below are all equivalent
<Link to="/posts">Navigate back to /posts</Link>
<Link from="/posts" to=".">
Navigate back to /posts
</Link>
// the below are all equivalent
<Link to="/">Navigate to root</Link>
<Link from="/posts" to="..">
Navigate to root
</Link>
</div>
)
}
Suchparameter sind eine großartige Möglichkeit, zusätzliche Kontexte zu einer Route bereitzustellen. Zum Beispiel möchten Sie vielleicht eine Suchanfrage für eine Suchseite bereitstellen.
const link = (
<Link
to="/search"
search={{
query: 'tanstack',
}}
>
Search
</Link>
)
const link = (
<Link
to="/search"
search={{
query: 'tanstack',
}}
>
Search
</Link>
)
Es ist auch üblich, einen einzelnen Suchparameter zu aktualisieren, ohne weitere Informationen über die vorhandene Route anzugeben. Zum Beispiel möchten Sie vielleicht die Seitenzahl eines Suchergebnisses aktualisieren.
const link = (
<Link
to="."
search={(prev) => ({
...prev,
page: prev.page + 1,
})}
>
Next Page
</Link>
)
const link = (
<Link
to="."
search={(prev) => ({
...prev,
page: prev.page + 1,
})}
>
Next Page
</Link>
)
Suchparameter sind ein hochdynamischer Mechanismus zur Zustandsverwaltung. Daher ist es wichtig sicherzustellen, dass Sie die richtigen Typen an Ihre Suchparameter übergeben. Wir werden in einem späteren Abschnitt detailliert darauf eingehen, wie Sie die Typsicherheit von Suchparametern und andere großartige Funktionen validieren und sicherstellen!
Hash-Links sind eine großartige Möglichkeit, auf einen bestimmten Abschnitt einer Seite zu verlinken. Zum Beispiel möchten Sie vielleicht auf einen bestimmten Abschnitt eines Blogbeitrags verlinken.
const link = (
<Link
to="/blog/post/$postId"
params={{
postId: 'my-first-blog-post',
}}
hash="section-1"
>
Section 1
</Link>
)
const link = (
<Link
to="/blog/post/$postId"
params={{
postId: 'my-first-blog-post',
}}
hash="section-1"
>
Section 1
</Link>
)
Optionale Pfadparameter bieten flexible Navigationsmuster, bei denen Sie Parameter nach Bedarf einschließen oder weglassen können. Optionale Parameter verwenden die Syntax {-$paramName} und bieten eine feingranulare Kontrolle über die URL-Struktur.
Bei der Navigation mit optionalen Parametern haben Sie zwei Hauptstrategien:
Aktuelle Parameter vererben Verwenden Sie params: {}, um alle aktuellen Routenparameter zu vererben.
// Inherits current route parameters
<Link to="/posts/{-$category}" params={{}}>
All Posts
</Link>
// Inherits current route parameters
<Link to="/posts/{-$category}" params={{}}>
All Posts
</Link>
Parameter entfernen
Setzen Sie Parameter auf undefined, um sie explizit zu entfernen.
// Removes the category parameter
<Link to="/posts/{-$category}" params={{ category: undefined }}>
All Posts
</Link>
// Removes the category parameter
<Link to="/posts/{-$category}" params={{ category: undefined }}>
All Posts
</Link>
// Navigate with optional parameter
<Link
to="/posts/{-$category}"
params={{ category: 'tech' }}
>
Tech Posts
</Link>
// Navigate without optional parameter
<Link
to="/posts/{-$category}"
params={{ category: undefined }}
>
All Posts
</Link>
// Navigate using parameter inheritance
<Link
to="/posts/{-$category}"
params={{}}
>
Current Category
</Link>
// Navigate with optional parameter
<Link
to="/posts/{-$category}"
params={{ category: 'tech' }}
>
Tech Posts
</Link>
// Navigate without optional parameter
<Link
to="/posts/{-$category}"
params={{ category: undefined }}
>
All Posts
</Link>
// Navigate using parameter inheritance
<Link
to="/posts/{-$category}"
params={{}}
>
Current Category
</Link>
Funktionsbasierte Parameteraktualisierungen sind besonders nützlich bei optionalen Parametern.
// Remove a parameter using function syntax
<Link
to="/posts/{-$category}"
params={(prev) => ({ ...prev, category: undefined })}
>
Clear Category
</Link>
// Update a parameter while keeping others
<Link
to="/articles/{-$category}/{-$slug}"
params={(prev) => ({ ...prev, category: 'news' })}
>
News Articles
</Link>
// Conditionally set parameters
<Link
to="/posts/{-$category}"
params={(prev) => ({
...prev,
category: someCondition ? 'tech' : undefined
})}
>
Conditional Category
</Link>
// Remove a parameter using function syntax
<Link
to="/posts/{-$category}"
params={(prev) => ({ ...prev, category: undefined })}
>
Clear Category
</Link>
// Update a parameter while keeping others
<Link
to="/articles/{-$category}/{-$slug}"
params={(prev) => ({ ...prev, category: 'news' })}
>
News Articles
</Link>
// Conditionally set parameters
<Link
to="/posts/{-$category}"
params={(prev) => ({
...prev,
category: someCondition ? 'tech' : undefined
})}
>
Conditional Category
</Link>
Wenn Sie mit mehreren optionalen Parametern arbeiten, können Sie mischen und anpassen, welche davon eingeschlossen werden sollen.
// Navigate with some optional parameters
<Link
to="/posts/{-$category}/{-$slug}"
params={{ category: 'tech', slug: undefined }}
>
Tech Posts
</Link>
// Remove all optional parameters
<Link
to="/posts/{-$category}/{-$slug}"
params={{ category: undefined, slug: undefined }}
>
All Posts
</Link>
// Set multiple parameters
<Link
to="/posts/{-$category}/{-$slug}"
params={{ category: 'tech', slug: 'react-tips' }}
>
Specific Post
</Link>
// Navigate with some optional parameters
<Link
to="/posts/{-$category}/{-$slug}"
params={{ category: 'tech', slug: undefined }}
>
Tech Posts
</Link>
// Remove all optional parameters
<Link
to="/posts/{-$category}/{-$slug}"
params={{ category: undefined, slug: undefined }}
>
All Posts
</Link>
// Set multiple parameters
<Link
to="/posts/{-$category}/{-$slug}"
params={{ category: 'tech', slug: 'react-tips' }}
>
Specific Post
</Link>
Optionale Parameter funktionieren nahtlos mit erforderlichen Parametern.
// Required 'id', optional 'tab'
<Link
to="/users/$id/{-$tab}"
params={{ id: '123', tab: 'settings' }}
>
User Settings
</Link>
// Remove optional parameter while keeping required
<Link
to="/users/$id/{-$tab}"
params={{ id: '123', tab: undefined }}
>
User Profile
</Link>
// Use function style with mixed parameters
<Link
to="/users/$id/{-$tab}"
params={(prev) => ({ ...prev, tab: 'notifications' })}
>
User Notifications
</Link>
// Required 'id', optional 'tab'
<Link
to="/users/$id/{-$tab}"
params={{ id: '123', tab: 'settings' }}
>
User Settings
</Link>
// Remove optional parameter while keeping required
<Link
to="/users/$id/{-$tab}"
params={{ id: '123', tab: undefined }}
>
User Profile
</Link>
// Use function style with mixed parameters
<Link
to="/users/$id/{-$tab}"
params={(prev) => ({ ...prev, tab: 'notifications' })}
>
User Notifications
</Link>
Präfix- und Suffixparameter Optionale Parameter mit Präfix/Suffix funktionieren mit der Navigation.
// Navigate to file with optional name
<Link
to="/files/prefix{-$name}.txt"
params={{ name: 'document' }}
>
Document File
</Link>
// Navigate to file without optional name
<Link
to="/files/prefix{-$name}.txt"
params={{ name: undefined }}
>
Default File
</Link>
// Navigate to file with optional name
<Link
to="/files/prefix{-$name}.txt"
params={{ name: 'document' }}
>
Document File
</Link>
// Navigate to file without optional name
<Link
to="/files/prefix{-$name}.txt"
params={{ name: undefined }}
>
Default File
</Link>
Alle optionalen Parameter Routen, bei denen alle Parameter optional sind.
// Navigate to specific date
<Link
to="/{-$year}/{-$month}/{-$day}"
params={{ year: '2023', month: '12', day: '25' }}
>
Christmas 2023
</Link>
// Navigate to partial date
<Link
to="/{-$year}/{-$month}/{-$day}"
params={{ year: '2023', month: '12', day: undefined }}
>
December 2023
</Link>
// Navigate to root with all parameters removed
<Link
to="/{-$year}/{-$month}/{-$day}"
params={{ year: undefined, month: undefined, day: undefined }}
>
Home
</Link>
// Navigate to specific date
<Link
to="/{-$year}/{-$month}/{-$day}"
params={{ year: '2023', month: '12', day: '25' }}
>
Christmas 2023
</Link>
// Navigate to partial date
<Link
to="/{-$year}/{-$month}/{-$day}"
params={{ year: '2023', month: '12', day: undefined }}
>
December 2023
</Link>
// Navigate to root with all parameters removed
<Link
to="/{-$year}/{-$month}/{-$day}"
params={{ year: undefined, month: undefined, day: undefined }}
>
Home
</Link>
Optionale Parameter funktionieren hervorragend in Kombination mit Suchparametern.
// Combine optional path params with search params
<Link
to="/posts/{-$category}"
params={{ category: 'tech' }}
search={{ page: 1, sort: 'newest' }}
>
Tech Posts - Page 1
</Link>
// Remove path param but keep search params
<Link
to="/posts/{-$category}"
params={{ category: undefined }}
search={(prev) => prev}
>
All Posts - Same Filters
</Link>
// Combine optional path params with search params
<Link
to="/posts/{-$category}"
params={{ category: 'tech' }}
search={{ page: 1, sort: 'newest' }}
>
Tech Posts - Page 1
</Link>
// Remove path param but keep search params
<Link
to="/posts/{-$category}"
params={{ category: undefined }}
search={(prev) => prev}
>
All Posts - Same Filters
</Link>
Alle gleichen Muster funktionieren mit imperativer Navigation.
function Component() {
const navigate = useNavigate()
const clearFilters = () => {
navigate({
to: '/posts/{-$category}/{-$tag}',
params: { category: undefined, tag: undefined },
})
}
const setCategory = (category: string) => {
navigate({
to: '/posts/{-$category}/{-$tag}',
params: (prev) => ({ ...prev, category }),
})
}
const applyFilters = (category?: string, tag?: string) => {
navigate({
to: '/posts/{-$category}/{-$tag}',
params: { category, tag },
})
}
}
function Component() {
const navigate = useNavigate()
const clearFilters = () => {
navigate({
to: '/posts/{-$category}/{-$tag}',
params: { category: undefined, tag: undefined },
})
}
const setCategory = (category: string) => {
navigate({
to: '/posts/{-$category}/{-$tag}',
params: (prev) => ({ ...prev, category }),
})
}
const applyFilters = (category?: string, tag?: string) => {
navigate({
to: '/posts/{-$category}/{-$tag}',
params: { category, tag },
})
}
}
active & inactive PropsDie Link-Komponente unterstützt zwei zusätzliche Props: activeProps und inactiveProps. Diese Props sind Funktionen, die zusätzliche Props für die aktiven und inaktiven Zustände des Links zurückgeben. Alle hier übergebenen Props außer Stilen und Klassen überschreiben die ursprünglichen Props, die an Link übergeben wurden. Alle übergebenen Stile oder Klassen werden zusammengeführt.
Hier ist ein Beispiel
const link = (
<Link
to="/blog/post/$postId"
params={{
postId: 'my-first-blog-post',
}}
activeProps={{
style: {
fontWeight: 'bold',
},
}}
>
Section 1
</Link>
)
const link = (
<Link
to="/blog/post/$postId"
params={{
postId: 'my-first-blog-post',
}}
activeProps={{
style: {
fontWeight: 'bold',
},
}}
>
Section 1
</Link>
)
Zusätzlich zu den Props activeProps und inactiveProps fügt die Link-Komponente dem gerenderten Element ein data-status-Attribut hinzu, wenn es sich in einem aktiven Zustand befindet. Dieses Attribut ist active oder undefined, abhängig vom aktuellen Zustand des Links. Dies kann nützlich sein, wenn Sie Datenattribute zum Stylen Ihrer Links anstelle von Props bevorzugen.
Die Link-Komponente verfügt über eine activeOptions-Eigenschaft, die einige Optionen zur Bestimmung bietet, ob ein Link aktiv ist oder nicht. Die folgende Schnittstelle beschreibt diese Optionen:
export interface ActiveOptions {
// If true, the link will be active if the current route matches the `to` route path exactly (no children routes)
// Defaults to `false`
exact?: boolean
// If true, the link will only be active if the current URL hash matches the `hash` prop
// Defaults to `false`
includeHash?: boolean // Defaults to false
// If true, the link will only be active if the current URL search params inclusively match the `search` prop
// Defaults to `true`
includeSearch?: boolean
// This modifies the `includeSearch` behavior.
// If true, properties in `search` that are explicitly `undefined` must NOT be present in the current URL search params for the link to be active.
// defaults to `false`
explicitUndefined?: boolean
}
export interface ActiveOptions {
// If true, the link will be active if the current route matches the `to` route path exactly (no children routes)
// Defaults to `false`
exact?: boolean
// If true, the link will only be active if the current URL hash matches the `hash` prop
// Defaults to `false`
includeHash?: boolean // Defaults to false
// If true, the link will only be active if the current URL search params inclusively match the `search` prop
// Defaults to `true`
includeSearch?: boolean
// This modifies the `includeSearch` behavior.
// If true, properties in `search` that are explicitly `undefined` must NOT be present in the current URL search params for the link to be active.
// defaults to `false`
explicitUndefined?: boolean
}
Standardmäßig wird geprüft, ob der resultierende Pfadname ein Präfix der aktuellen Route ist. Wenn Suchparameter angegeben sind, wird geprüft, ob diese die Parameter im aktuellen Speicherort *inklusiv* übereinstimmen. Hashes werden standardmäßig nicht geprüft.
Zum Beispiel, wenn Sie sich auf der Route /blog/post/my-first-blog-post befinden, sind die folgenden Links aktiv:
const link1 = (
<Link to="/blog/post/$postId" params={{ postId: 'my-first-blog-post' }}>
Blog Post
</Link>
)
const link2 = <Link to="/blog/post">Blog Post</Link>
const link3 = <Link to="/blog">Blog Post</Link>
const link1 = (
<Link to="/blog/post/$postId" params={{ postId: 'my-first-blog-post' }}>
Blog Post
</Link>
)
const link2 = <Link to="/blog/post">Blog Post</Link>
const link3 = <Link to="/blog">Blog Post</Link>
Die folgenden Links sind jedoch nicht aktiv:
const link4 = (
<Link to="/blog/post/$postId" params={{ postId: 'my-second-blog-post' }}>
Blog Post
</Link>
)
const link4 = (
<Link to="/blog/post/$postId" params={{ postId: 'my-second-blog-post' }}>
Blog Post
</Link>
)
Es ist üblich, dass einige Links nur aktiv sind, wenn sie eine exakte Übereinstimmung sind. Ein gutes Beispiel dafür wäre ein Link zur Startseite. In solchen Szenarien können Sie die Option exact: true übergeben.
const link = (
<Link to="/" activeOptions={{ exact: true }}>
Home
</Link>
)
const link = (
<Link to="/" activeOptions={{ exact: true }}>
Home
</Link>
)
Dadurch wird sichergestellt, dass der Link nicht aktiv ist, wenn Sie sich auf einer Kindroute befinden.
Einige weitere Optionen, die Sie kennen sollten:
Die Link-Komponente akzeptiert eine Funktion für ihre Kinder, die es Ihnen ermöglicht, ihre isActive-Eigenschaft an Kinder weiterzugeben. Zum Beispiel könnten Sie eine Kindkomponente basierend darauf stylen, ob der Elternlink aktiv ist.
const link = (
<Link to="/blog/post">
{({ isActive }) => {
return (
<>
<span>My Blog Post</span>
<icon className={isActive ? 'active' : 'inactive'} />
</>
)
}}
</Link>
)
const link = (
<Link to="/blog/post">
{({ isActive }) => {
return (
<>
<span>My Blog Post</span>
<icon className={isActive ? 'active' : 'inactive'} />
</>
)
}}
</Link>
)
Die Link-Komponente unterstützt das automatische Vorabladen von Routen bei Absicht (derzeit Hover oder Touchstart). Dies kann als Standard in den Router-Optionen konfiguriert werden (worüber wir bald mehr sprechen werden) oder durch Übergabe eines preload='intent'-Props an die Link-Komponente. Hier ist ein Beispiel:
const link = (
<Link to="/blog/post/$postId" preload="intent">
Blog Post
</Link>
)
const link = (
<Link to="/blog/post/$postId" preload="intent">
Blog Post
</Link>
)
Mit aktivierter Vorabladung und relativ schnellen asynchronen Routenabhängigkeiten (falls vorhanden) kann dieser einfache Trick die wahrgenommene Leistung Ihrer Anwendung mit sehr wenig Aufwand steigern.
Was noch besser ist: Durch die Verwendung einer Cache-First-Bibliothek wie @tanstack/query bleiben vorab geladene Routen erhalten und sind für eine Stale-While-Revalidate-Erfahrung bereit, falls der Benutzer später zu dieser Route navigiert.
Zusammen mit der Vorabladung gibt es eine konfigurierbare Verzögerung, die bestimmt, wie lange ein Benutzer mit der Maus über einen Link fahren muss, um die vorab ladende Vorabladung auszulösen. Die Standardverzögerung beträgt 50 Millisekunden, aber Sie können dies ändern, indem Sie einen preloadDelay-Prop an die Link-Komponente übergeben, mit der Anzahl der Millisekunden, die Sie warten möchten.
const link = (
<Link to="/blog/post/$postId" preload="intent" preloadDelay={100}>
Blog Post
</Link>
)
const link = (
<Link to="/blog/post/$postId" preload="intent" preloadDelay={100}>
Blog Post
</Link>
)
⚠️ Aufgrund der integrierten Funktionalitäten der Link-Komponente bezüglich href, Cmd/Strg + Klickbarkeit und aktiven/inaktiven Funktionen wird empfohlen, die Link-Komponente anstelle von useNavigate für alles zu verwenden, womit der Benutzer interagieren kann (z. B. Links, Schaltflächen). Es gibt jedoch einige Fälle, in denen useNavigate zur Behandlung von Nebeneffekt-Navigationen (z. B. eine erfolgreiche asynchrone Aktion, die zu einer Navigation führt) erforderlich ist.
Der Hook useNavigate gibt eine navigate-Funktion zurück, die aufgerufen werden kann, um imperativ zu navigieren. Es ist eine großartige Möglichkeit, von einem Nebeneffekt zu einer Route zu navigieren (z. B. eine erfolgreiche asynchrone Aktion). Hier ist ein Beispiel:
function Component() {
const navigate = useNavigate({ from: '/posts/$postId' })
const handleSubmit = async (e: FrameworkFormEvent) => {
e.preventDefault()
const response = await fetch('/posts', {
method: 'POST',
body: JSON.stringify({ title: 'My First Post' }),
})
const { id: postId } = await response.json()
if (response.ok) {
navigate({ to: '/posts/$postId', params: { postId } })
}
}
}
function Component() {
const navigate = useNavigate({ from: '/posts/$postId' })
const handleSubmit = async (e: FrameworkFormEvent) => {
e.preventDefault()
const response = await fetch('/posts', {
method: 'POST',
body: JSON.stringify({ title: 'My First Post' }),
})
const { id: postId } = await response.json()
if (response.ok) {
navigate({ to: '/posts/$postId', params: { postId } })
}
}
}
🧠 Wie oben gezeigt, können Sie die Option from übergeben, um die Route anzugeben, von der aus in dem Hook-Aufruf navigiert werden soll. Während dies auch möglich ist, wenn Sie es jedes Mal, wenn Sie es aufrufen, an die resultierende navigate-Funktion übergeben, wird empfohlen, es hier zu übergeben, um potenzielle Fehler zu reduzieren und auch weniger tippen zu müssen!
navigate OptionenDie von useNavigate zurückgegebene Funktion navigate akzeptiert die Schnittstelle NavigateOptions.
Gelegentlich müssen Sie möglicherweise sofort navigieren, wenn eine Komponente gemountet wird. Ihr erster Instinkt könnte sein, nach useNavigate und einem sofortigen Nebeneffekt (z. B. useEffect) zu greifen, aber das ist unnötig. Stattdessen können Sie die Navigate-Komponente rendern, um das gleiche Ergebnis zu erzielen.
function Component() {
return <Navigate to="/posts/$postId" params={{ postId: 'my-first-post' }} />
}
function Component() {
return <Navigate to="/posts/$postId" params={{ postId: 'my-first-post' }} />
}
Betrachten Sie die Navigate-Komponente als eine Möglichkeit, sofort zu einer Route zu navigieren, wenn eine Komponente gemountet wird. Sie ist eine großartige Möglichkeit, clientseitige Weiterleitungen zu behandeln. Sie ist *definitiv nicht* ein Ersatz für die verantwortungsvolle Behandlung von serverseitig bewussten Weiterleitungen auf dem Server.
Die Methode router.navigate ist identisch mit der Funktion navigate, die von useNavigate zurückgegeben wird, und akzeptiert dieselbe Schnittstelle NavigateOptions. Im Gegensatz zum Hook useNavigate ist sie überall dort verfügbar, wo Ihre router-Instanz verfügbar ist, und ist somit eine großartige Möglichkeit, imperativ von überall in Ihrer Anwendung zu navigieren, auch außerhalb Ihres Frameworks.
Der Hook useMatchRoute und die Komponente <MatchRoute> sind dasselbe, aber der Hook ist etwas flexibler. Beide akzeptieren die Standard-Navigationsschnittstelle ToOptions entweder als Optionen oder als Props und geben true/false zurück, wenn diese Route aktuell übereinstimmt. Sie hat auch eine praktische pending-Option, die true zurückgibt, wenn die Route gerade ausgeführt wird (z. B. wenn eine Route gerade zu dieser Route wechselt). Dies kann äußerst nützlich sein, um optimistische Benutzeroberflächen rund um die Navigation des Benutzers anzuzeigen.
function Component() {
return (
<div>
<Link to="/users">
Users
<MatchRoute to="/users" pending>
<Spinner />
</MatchRoute>
</Link>
</div>
)
}
function Component() {
return (
<div>
<Link to="/users">
Users
<MatchRoute to="/users" pending>
<Spinner />
</MatchRoute>
</Link>
</div>
)
}
Die Komponentenversion <MatchRoute> kann auch mit einer Funktion als Kinder verwendet werden, um etwas zu rendern, wenn die Route übereinstimmt.
function Component() {
return (
<div>
<Link to="/users">
Users
<MatchRoute to="/users" pending>
{(match) => {
return <Spinner show={match} />
}}
</MatchRoute>
</Link>
</div>
)
}
function Component() {
return (
<div>
<Link to="/users">
Users
<MatchRoute to="/users" pending>
{(match) => {
return <Spinner show={match} />
}}
</MatchRoute>
</Link>
</div>
)
}
Die Hook-Version useMatchRoute gibt eine Funktion zurück, die programmatisch aufgerufen werden kann, um zu prüfen, ob eine Route übereinstimmt.
function Component() {
const matchRoute = useMatchRoute()
useEffect(() => {
if (matchRoute({ to: '/users', pending: true })) {
console.info('The /users route is matched and pending')
}
})
return (
<div>
<Link to="/users">Users</Link>
</div>
)
}
function Component() {
const matchRoute = useMatchRoute()
useEffect(() => {
if (matchRoute({ to: '/users', pending: true })) {
console.info('The /users route is matched and pending')
}
})
return (
<div>
<Link to="/users">Users</Link>
</div>
)
}
Puh! Das ist eine Menge Navigation! Hoffentlich fühlen Sie sich jetzt ziemlich gut damit, sich in Ihrer Anwendung zurechtzufinden. Lassen Sie uns weitermachen!
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.