There are two ways to access router within components.
useRouter() (recommended)withRouter()useRouterimport {useRouter} from "blitz"
function Thing({href}) {
const router = useRouter()
return (
<div
style={{
color: router.pathname === href ? "red" : "black",
}}
/>
)
}
export default Thing
useRouteris a React Hook, meaning it cannot be used with classes. You can either use withRouter or wrap your class in a function component.
withRouterimport {withRouter} from "blitz"
function Page({router}) {
return <p>{router.pathname}</p>
}
export default withRouter(Page)router objectHere's the definition of the router object returned by useRouter and
withRouter:
pathname: String - Current route. That is the path of the page in
/pagesquery: Object - All the query string parameters from the current
url. Parameter type is always string.params: Object - All the dynamic route parameters for the current
route. Parameter types are string or string[].asPath: String - Actual path (including the query) shown in the
browserpush(): Make page navigationreplace(): Make page navigation without adding to
browser historyback(): Navigate to previous history locationreload(): Reload the pageprefetch(): Prefetch pages for faster client-side
transitionsevents: Subscribe to various router eventsbeforePopState(): For advanced routing needsThe following router APIs can also be used via
import {Router} from 'blitz'
Handles client-side transitions, this method is useful for cases where
<Link> is not enough.
import {Router} from "blitz"
Router.push(url, as, options)url - The URL to navigate to. This is usually the name of a pageas - Optional decorator for the URL that will be shown in the browser.
Defaults to urloptions - Optional object with the following configuration options:shallow: Update the path of the current page without
rerunning getStaticProps or
getServerSideProps. Defaults to falseYou don't need to use
Routerfor external URLs, window.location is better suited for those cases.
Navigating to pages/about.js, which is a predefined route:
import {Router} from "blitz"
function Page() {
return <span onClick={() => Router.push("/about")}>Click me</span>
}Navigating pages/post/[pid].js, which is a dynamic route:
import {Router} from "blitz"
function Page() {
return (
<span onClick={() => Router.push("/post/[pid]", "/post/abc")}>
Click me
</span>
)
}You can use an URL object in the same way you can use it for
<Link>. Works for both the url and as parameters:
import {Router} from "blitz"
const handler = () => {
Router.push({
pathname: "/about",
query: {name: "Vercel"},
})
}
function ReadMore() {
return (
<div>
Click <span onClick={handler}>here</span> to read more
</div>
)
}
export default ReadMoreSimilar to the replace prop in <Link>, Router.replace will
prevent adding a new URL entry into the history stack, take a look at
the following example:
import {Router} from "blitz"
Router.replace("/home")The API for Router.replace is exactly the same as that used for
Router.push.
Navigate back in history. Equivalent to clicking the browser’s back
button. It executes window.history.back().
import {Router} from "blitz"
Router.back()Reload the current URL. Equivalent to clicking the browser’s refresh
button. It executes window.location.reload().
import {Router} from "blitz"
Router.reload()Prefetch pages for faster client-side transitions. This method is only
useful for navigations without <Link> because it takes care of
prefetching pages automatically.
This is a production only feature. Next.js doesn't prefetch pages on development.
import {Router} from "blitz"
Router.prefetch(url, as)url - The path to a page inside the pages directoryas - Optional decorator for url, used to prefetch
dynamic routes. Defaults to urlLet's say you have a login page, and after a login, you redirect the user to the dashboard. For that case, we can prefetch the dashboard to make a faster transition, like in the following example:
import {Router} from "blitz"
export default function Login() {
const handleSubmit = React.useCallback((e) => {
e.preventDefault()
fetch("/api/login", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
/* Form data */
}),
}).then((res) => {
// Do a fast client-side transition to the already prefetched dashboard page
if (res.ok) Router.push("/dashboard")
})
}, [])
React.useEffect(() => {
// Prefetch the dashboard page as the user will go there after the login
Router.prefetch("/dashboard")
}, [])
return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
<button type="submit">Login</button>
</form>
)
}You can listen to different events happening inside the Router. Here's a list of supported events:
routeChangeStart(url) - Fires when a route starts to changerouteChangeComplete(url) - Fires when a route changed completelyrouteChangeError(err, url) - Fires when there's an error when changing
routes, or a route load is cancellederr.cancelled - Indicates if the navigation was cancelledbeforeHistoryChange(url) - Fires right before changing the browser's
historyhashChangeStart(url) - Fires when the hash will change but not the
pagehashChangeComplete(url) - Fires when the hash has changed but not the
pageHere
urlis the URL shown in the browser. If you callRouter.push(url, as)(or similar), then the value ofurlwill beas.
For example, to listen to the router event routeChangeStart, do the
following:
import {Router} from "blitz"
const handleRouteChange = (url) => {
console.log("App is changing to: ", url)
}
Router.events.on("routeChangeStart", handleRouteChange)If you no longer want to listen to the event, unsubscribe with the off
method:
import {Router} from "blitz"
Router.events.off("routeChangeStart", handleRouteChange)If a route load is cancelled (for example, by clicking two links rapidly
in succession), routeChangeError will fire. And the passed err will
contain a cancelled property set to true, as in the following example:
import {Router} from "blitz"
Router.events.on("routeChangeError", (err, url) => {
if (err.cancelled) {
console.log(`Route to ${url} was cancelled!`)
}
})Router events should be registered when a component mounts (useEffect or componentDidMount / componentWillUnmount) or imperatively when an event happens, as in the following example:
import {Router} from "blitz"
useEffect(() => {
const handleRouteChange = (url) => {
console.log("App is changing to: ", url)
}
Router.events.on("routeChangeStart", handleRouteChange)
return () => {
Router.events.off("routeChangeStart", handleRouteChange)
}
}, [])In some cases (for example, if using a Custom Server), you may wish to listen to popstate and do something before the router acts on it.
You could use this to manipulate the request, or force a SSR refresh, as in the following example:
import {Router} from "blitz"
Router.beforePopState(({url, as, options}) => {
// I only want to allow these two routes!
if (as !== "/" && as !== "/other") {
// Have SSR render bad routes as a 404.
window.location.href = as
return false
}
return true
})Router.beforePopState(cb: () => boolean)
cb - The function to run on incoming popstate events. The function
receives the state of the event as an object with the following props:url: String - the route for the new state. This is usually the
name of a pageas: String - the url that will be shown in the browseroptions: Object - Additional options sent by
Router.pushIf the function you pass into beforePopState returns false, Router
will not handle popstate and you'll be responsible for handling it, in
that case. See Disabling file-system routing.