ToOptions-SchnittstelleNavigateOptions-SchnittstelleLinkOptions-Schnittstelle<Link>-Komponente"." und ".."active & inactive Propsdata-status-AttributactiveOptionsisActive an Kinder übergebenuseNavigatenavigate-OptionenNavigate-Komponenterouter.navigateuseMatchRoute und <MatchRoute>Ob Sie es glauben oder nicht, jede Navigation innerhalb einer App ist relativ, auch wenn Sie keine explizite relative Pfadsyntax verwenden (../../somewhere). Jedes Mal, wenn auf einen Link geklickt wird oder ein imperativer Navigationsaufruf erfolgt, gibt es immer einen Ursprungspfad und einen Zielpfad, was bedeutet, dass Sie von einer Route zu einer anderen Route navigieren.
TanStack Router behält dieses konstante Konzept der relativen Navigation bei jeder Navigation im Hinterkopf, sodass Sie in der API ständig zwei Eigenschaften sehen werden
⚠️ Wenn kein from-Routenpfad angegeben wird, geht der Router davon aus, dass Sie von der Stammroute / aus 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, je nach API. Das bedeutet, dass Sie Navigation und Routenabgleich einmal lernen und dieselbe Syntax und Konzepte in der gesamten Bibliothek verwenden können.
Dies ist die Kernschnittstelle 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, können Sie so reine Zeichenketten vermeiden und stattdessen typsichere Routenreferenzen 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 Kernschnittstelle 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 all den Schnittstellen im Hinterkopf, sprechen wir nun über die verschiedenen Navigations-APIs, die Ihnen zur Verfügung stehen
router.navigate()⚠️ 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 Sie Ihre Anwendung mounten, verwenden Sie 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 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)
}
Lassen Sie uns einen einfachen statischen Link erstellen!
import { Link } from '@tanstack/react-router'
const link = <Link to="/about">About</Link>
import { Link } from '@tanstack/react-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 jedem Fall 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 bereitgestellt. Das bedeutet, dass der obige Link immer zur Route /about navigiert, unabhängig davon, auf welcher Route Sie sich gerade befinden.
Relative Links können mit einem from-Routenpfad kombiniert werden. Wenn kein from-Routenpfad bereitgestellt wird, werden relative Pfade standardmäßig zur aktuell aktiven Position verwendet.
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, route.fullPath als from-Routenpfad anzugeben. Das liegt daran, dass route.fullPath eine Referenz ist, die sich ändert, wenn Sie Ihre Anwendung refaktorieren. Manchmal ist es jedoch nicht möglich, die Route direkt zu importieren. In diesem Fall ist es in Ordnung, den Routenpfad direkt als Zeichenkette anzugeben. Er wird trotzdem wie gewohnt typsicher geprüft!
Oft möchten Sie möglicherweise den aktuellen Standort oder einen anderen from-Pfad neu laden, um beispielsweise 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, der den aktuellen Standort oder den angegebenen from-Pfad neu lädt.
Eine weitere häufige Anforderung ist die Navigation eine Route zurück relativ zum aktuellen Standort oder einem anderen Pfad. Durch Angabe eines to-Routenpfads von ".." wird die Navigation zur ersten übergeordneten Route aufgelöst, die dem aktuellen Standort vorausgeht.
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>
)
}
Search-Parameter sind eine großartige Möglichkeit, zusätzliche Kontexte für eine Route bereitzustellen. Sie möchten beispielsweise 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 Search-Parameter aktualisieren zu wollen, ohne andere Informationen über die vorhandene Route bereitzustellen. Sie möchten beispielsweise die Seitennummer 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>
)
Search-Parameter sind ein hochdynamischer Mechanismus zur Zustandsverwaltung, daher ist es wichtig sicherzustellen, dass Sie die richtigen Typen an Ihre Search-Parameter übergeben. In einem späteren Abschnitt werden wir detailliert sehen, wie Sie Search-Parameter-Typen sowie andere großartige Funktionen validieren und sicherstellen können!
Hash-Links sind eine großartige Möglichkeit, zu einem bestimmten Abschnitt einer Seite zu verlinken. Sie möchten beispielsweise zu einem 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 detaillierte Kontrolle über die URL-Struktur.
Bei der Navigation mit optionalen Parametern haben Sie zwei Hauptstrategien
Erben aktueller Parameter Verwenden Sie params: {}, um alle aktuellen Routenparameter zu erben
// Inherits current route parameters
<Link to="/posts/{-$category}" params={{}}>
All Posts
</Link>
// Inherits current route parameters
<Link to="/posts/{-$category}" params={{}}>
All Posts
</Link>
Entfernen von Parametern
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>
Beim Arbeiten mit mehreren optionalen Parametern 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 lassen sich gut mit Search-Parametern kombinieren
// 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 auch bei 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 Props außer Stilen und Klassen, die hier übergeben werden, ü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 ein data-status-Attribut zum gerenderten Element hinzu, wenn es sich im aktiven Zustand befindet. Dieses Attribut ist entweder 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.
activeOptionsDie Link-Komponente verfügt über eine Eigenschaft activeOptions, 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 im aktuellen Standort vorhandenen Parameter inklusiv abgleichen. Hashes werden standardmäßig nicht geprüft.
Wenn Sie sich beispielsweise 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 hierfür wäre ein Link zur Startseite. In solchen Fällen 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>
)
Dies stellt sicher, dass der Link nicht aktiv ist, wenn Sie sich auf einer untergeordneten Route befinden.
Ein paar weitere Optionen, die Sie beachten sollten
isActive an Kinder übergebenDie Link-Komponente akzeptiert eine Funktion als Kinder, wodurch Sie ihre isActive-Eigenschaft an Kinder weitergeben können. Sie könnten beispielsweise eine Kindkomponente basierend darauf stylen, ob der übergeordnete Link 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 die automatische Vorabladung 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 geringem Aufwand steigern.
Was noch besser ist, ist, dass durch die Verwendung einer Cache-First-Bibliothek wie @tanstack/query, vorab geladene Routen bestehen bleiben und für eine Stale-While-Revalidate-Erfahrung bereit sind, wenn der Benutzer sich später entscheidet, zu der Route zu navigieren.
Zusammen mit der Vorabladung gibt es eine konfigurierbare Verzögerung, die bestimmt, wie lange ein Benutzer über einen Link schweben muss, um die absichtsbasierte 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 mit der gewünschten Anzahl von Millisekunden übergeben
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 Funktionen der Link-Komponente in Bezug auf href, Cmd/Strg + Klickbarkeit und aktive/inaktive Fähigkeiten 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 erforderlich ist, um Nebeneffektnavigationen zu handhaben (z. B. eine erfolgreiche asynchrone Aktion, die zu einer Navigation führt).
Der useNavigate-Hook gibt eine navigate-Funktion zurück, die aufgerufen werden kann, um imperativ zu navigieren. Dies ist eine großartige Möglichkeit, von einem Nebeneffekt (z. B. einer erfolgreichen asynchronen Aktion) zu einer Route zu navigieren. 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 in dem Hook-Aufruf navigiert werden soll. Obwohl dies auch möglich ist, wenn Sie sie jedes Mal, wenn Sie sie aufrufen, in der resultierenden navigate-Funktion übergeben, wird empfohlen, sie hier zu übergeben, um potenzielle Fehler zu reduzieren und auch weniger tippen zu müssen!
Die von useNavigate zurückgegebene navigate-Funktion akzeptiert die NavigateOptions-Schnittstelle
Gelegentlich müssen Sie möglicherweise sofort navigieren, wenn eine Komponente gemountet wird. Ihr erster Gedanke könnte sein, zu useNavigate und einem sofortigen Nebeneffekt (z. B. useEffect) zu greifen, aber das ist unnötig. Stattdessen können Sie die Navigate-Komponente rendern, um dasselbe 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. Dies ist eine großartige Möglichkeit, nur clientseitige Weiterleitungen zu handhaben. Sie ist auf keinen Fall ein Ersatz für die verantwortungsvolle Handhabung serverseitiger Weiterleitungen auf dem Server.
Die Methode router.navigate ist dieselbe wie die von useNavigate zurückgegebene navigate-Funktion und akzeptiert dieselbe NavigateOptions-Schnittstelle. Im Gegensatz zum useNavigate-Hook ist sie überall 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-Navigations- ToOptions-Schnittstelle entweder als Optionen oder Props und geben true/false zurück, ob diese Route aktuell übereinstimmt. Sie verfügt auch über eine praktische pending-Option, die true zurückgibt, wenn die Route gerade bearbeitet wird (z. B. eine Route, die gerade zu dieser Route wechselt). Dies kann äußerst nützlich sein, um optimistische Benutzeroberflächen rund um die Navigation eines 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 überprü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! Dennoch fühlen Sie sich hoffentlich ziemlich gut im Umgang mit Ihrer Anwendung. Machen wir weiter!
Ihre wöchentliche Dosis JavaScript-Nachrichten. Jeden Montag kostenlos an über 100.000 Entwickler geliefert.