useRouter
Navigate from code: push, replace, back, forward, refresh the current page in place, or prefetch a page ahead of time.
import { useRouter } from '@gio.js/react';
export function CloseButton() {
const router = useRouter();
return <button onClick={() => router.back()}>Close</button>;
}Reference
useRouter() takes no parameters and returns a GioRouter: one frozen object, the same on every render and in every component.
| Field | Type | Default | Description |
|---|---|---|---|
push(href, options?) | Promise<void> | - | Navigate to href, adding a history entry. |
replace(href, options?) | Promise<void> | - | Navigate to href, replacing the current history entry. |
back() | void | - | Go back one entry (history.back()). The router renders that page and restores its scroll position. |
forward() | void | - | Go forward one entry (history.forward()). |
refresh() | Promise<void> | - | Fetch the current page again and render it in place: same URL, scroll position and component state, fresh props. |
prefetch(href) | void | - | Fetch a page into the prefetch cache, as a hovered GioLink does. |
Options
The second argument of push and replace (the type RouterNavigateOptions):
| Option | Type | Default | Description |
|---|---|---|---|
scroll | boolean | true | Scroll to the top of the new page, or to the element its #hash names. false keeps the position. |
transition | 'fade' | 'slide-left' | 'slide-up' | 'scale' | false | false | Run the swap in a view transition, like <GioLink transition>. |
push and replace
hrefis resolved against the current URL, so a path (/posts/2), a query alone (?page=2) and a hash (#comments) all work.- A same-origin page is fetched (or taken from a fresh prefetch) and rendered in place, then the router scrolls and moves focus. A hash on the current page only scrolls.
- Another origin, an answer that is not a GioJS page, a network failure or a new deployment becomes a full page load (
location.assign, orlocation.replaceforreplace). - A URL that is not
http:orhttps:(javascript:,mailto:,data:) is refused: the promise rejects with aTypeError, sorouter.push(userInput)can never run script. - The promise resolves once the new page is on screen, or once a full load has started. A navigation overtaken by a newer one resolves without rendering anything.
refresh
router.refresh() empties the prefetch cache and fetches the current URL with cache: 'no-cache', so getServerSideProps runs again (or the server's page cache answers, for a page with revalidate). The answer is rendered into the same React root: layouts and the page keep their state, the scroll position and the history entry stay. When the answer is not a GioJS page, the browser reloads.
prefetch
prefetch(href) fetches a same-origin page into the cache the next navigation to it uses (30 seconds, at most 50 pages). It does nothing for other origins, for the current page and for a page already cached, and its request counts against the server's prefetch budget.
Examples
Navigating after a client-side request
import { useState } from 'react';
import { href, useRouter } from '@gio.js/react';
export function Editor() {
const router = useRouter();
const [title, setTitle] = useState('');
async function save() {
const res = await fetch('/api/posts', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ title }),
});
const { id } = (await res.json()) as { id: string };
await router.push(href('/posts/:id', { id }));
}
return (
<>
<input value={title} onChange={(e) => setTitle(e.target.value)} />
<button onClick={save}>Publish</button>
</>
);
}Refreshing data after a change
import { useRouter } from '@gio.js/react';
export function MarkAllRead() {
const router = useRouter();
async function markAll() {
await fetch('/api/inbox/read', { method: 'POST' });
await router.refresh(); // getServerSideProps runs again; state and scroll stay
}
return <button onClick={markAll}>Mark all as read</button>;
}Prefetching the likely next page
Fetch the page a visitor will most likely open next once this one is on screen, so the click renders it without waiting.
import { useEffect } from 'react';
import { GioLink, useRouter } from '@gio.js/react';
export function CheckoutButton() {
const router = useRouter();
useEffect(() => {
router.prefetch('/checkout');
}, [router]);
return <GioLink href="/checkout" prefetch={false}>Checkout</GioLink>;
}Paging without scrolling
import { useRouter, useSearchParams } from '@gio.js/react';
export function Pager() {
const router = useRouter();
const page = Number(useSearchParams().get('page') ?? '1');
return (
<button onClick={() => void router.push(`?page=${page + 1}`, { scroll: false })}>
Next page
</button>
);
}Good to know
- Every navigation asks the server for the page (unless a fresh prefetch has it). There is no "shallow" mode that changes the URL without fetching.
- The router holds no URL state: read
usePathname,useParamsanduseSearchParams. - During server rendering every method does nothing (
pushresolves at once). Call them from event handlers and effects. - Any same-origin
fetch()other thanGET,HEADorOPTIONSempties the prefetch cache, so a navigation after a mutation never shows a page fetched before it. - Outside components, use
navigate(href, options), which also takesreplace.
Related
- Linking & Navigating - soft navigation, scroll and focus.
<GioLink>- declarative navigation.href- typed paths.navigate- the function behindpushandreplace.
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Introduced: push, replace, back, forward, refresh and prefetch. |