DocsBuild
Linking and navigating
With client routing (useCSR = True), a link between two pages swaps the page in the browser instead
of reloading the document. The layouts keep their state.
Plain links already work
Every <a href> to a page of your project navigates on the client, with no component and no marker:
<a href="/about">About</a>
A link is left to the browser, and loads the page normally, when:
- a modifier key is held, or the button is not the main one;
- it has
target(other than_self),download,rel="external"ordata-nexy-reload; - the
hrefis another origin, amailto:ortel:link, or only a#fragment; - the path matches no client route, so the server answers it.
Link
Link is the same anchor with what a plain one cannot do: its href is checked against your routes,
it warms the target page, and it knows when it points at the current page. Nexy generates the Link
of your framework in __nexy__/src when you run nx dev or nx build.
| Framework | Import |
|---|---|
| React, Preact, Solid, Vue | import { Link } from "@nexy/client" |
| Svelte | import Link from "@nexy/Link.svelte" |
import { Link } from "@nexy/client";
export default function Nav() {
return (
<Link href="/dashboard" activeClassName="on">
Dashboard
</Link>
);
}
| Prop | Meaning |
|---|---|
href |
A route of the project (a typo is a type error), optionally with ?query or #fragment, or an external URL. |
replace |
Replace the history entry instead of adding one. |
scroll |
false keeps the scroll position after navigating. Default: true. |
prefetch |
'intent' (default) loads the page on hover, focus or touch; 'viewport' when the link scrolls into view; false never. |
activeClassName |
Added to the class while the link points at the current page or a page below it (activeClass in Vue and Svelte). |
exact |
Active only on the exact page. |
The link that points at the current page also gets aria-current="page".
Hooks
The location is available in every framework, in the idiom of that framework. During the first, server-side render the hooks answer with the URL of the request, so the page hydrates without a mismatch.
| React, Preact | Solid | Vue | Svelte | |
|---|---|---|---|---|
| Path | usePathname() |
usePathname() returns an accessor |
usePathname() returns a ref |
$pathname store |
| Route params | useParams() |
useParams() accessor |
useParams() ref |
$params store |
| Query | useSearchParams() |
useSearchParams() accessor |
useSearchParams() ref |
$searchParams store |
| Everything | useLocation() |
useLocation() accessor |
useLocation() ref |
$location store |
| Navigate | useRouter() |
useRouter() |
useRouter() |
router |
The query is a URLSearchParams. useRouter() and router give push(href), replace(href),
back(), forward(), refresh() and prefetch(href); push and replace accept
{ scroll: false }.
import { useParams, useRouter, useSearchParams } from "@nexy/client";
export default function User() {
const { id } = useParams<{ id: string }>();
const tab = useSearchParams().get("tab") ?? "profile";
const router = useRouter();
return <button onClick={() => router.push(`/users/${id}?tab=posts`)}>{tab}</button>;
}
Image
Image renders an <img> that is lazy by default and does not shift the layout when its size is
known.
| Framework | Import |
|---|---|
| React, Preact, Solid, Vue | import { Image } from "@nexy/client" |
| Svelte | import Image from "@nexy/Image.svelte" |
<Image src="/photo.jpg" alt="A mountain" width={800} height={600} />
altis required; usealt=""for a decorative image. Nexy warns once when it is missing.- With both
widthandheight, the attributes give the browser the aspect ratio and the image stays fluid (height: auto; max-width: 100%). priorityloads the image now at high priority, for the one that is visible on arrival.fillmakes the image cover its positioned parent, ignoringwidthandheight.sizesandsrcSetpass through. Nexy does not resize or convert images.
Link from a .nexy page
---
from nexy import Link
---
{{ Link("/about", "About", class_name="nav-link") }}
Link(href, children="", class_name=None, prefetch=True, **attrs) renders
<a href="/about" data-nexy-link="true">. Every attribute and the href are HTML-escaped.
What the router does
On a navigation, the router:
- matches the path against the client routes (
.tsx,.jsx,.vue,.svelte); - imports and renders the page and its layouts first, and only then
moves the URL with
history.pushState, so the address bar never shows a page that failed; - dispatches a
nexy:navigatedevent ondocument; - scrolls to the top, or to the
#fragmenttarget.
A newer navigation cancels an older one that is still rendering. If a page cannot render, the browser asks the server for it instead. The back and forward buttons render the page of that entry and restore its scroll position.
document.addEventListener("nexy:navigated", (event) => {
console.log(event.detail.pathname, event.detail.params);
});
The router starts only in a project with client routes, so a server-rendered project keeps the browser's own back button and scroll restoration.