Router
There are two ways to access
router
within components.useRouter()
(recommended)withRouter()
useRouter
import {useRouter} from "blitz"function Thing({href}) {const router = useRouter()return (<divstyle={{color: router.pathname === href ? "red" : "black",}}/>)}export default Thing
useRouter
is a React Hook, meaning it cannot be used with classes. You can either use withRouter or wrap your class in a function component.
withRouter
import {withRouter} from "blitz"function Page({router}) {return <p>{router.pathname}</p>}export default withRouter(Page)
router
object
Here's the definition of the
router
object returned by useRouter
and withRouter
:pathname
:String
- Current route. That is the path of the page in/pages
query
:Object
- All the query string parameters from the current url. Parameter type is alwaysstring
.params
:Object
- All the dynamic route parameters for the current route. Parameter types arestring
orstring[]
.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 needs
Router API
The following router APIs can also be used via
import {Router} from 'blitz'
Router.push
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 apage
as
- Optional decorator for the URL that will be shown in the browser. Defaults tourl
options
- Optional object with the following configuration options:shallow
: Update the path of the current page without rerunninggetStaticProps
orgetServerSideProps
. Defaults tofalse
You don't need to use
Router
for external URLs, window.location is better suited for those cases.
Usage
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>}
With URL object
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 ReadMore
Router.replace
Similar 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
.Router.back
Navigate back in history. Equivalent to clicking the browser’s back button. It executes
window.history.back()
.import {Router} from "blitz"Router.back()
Router.reload
Reload the current URL. Equivalent to clicking the browser’s refresh button. It executes
window.location.reload()
.import {Router} from "blitz"Router.reload()
Router.prefetch
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 apage
inside thepages
directoryas
- Optional decorator forurl
, used to prefetch dynamic routes. Defaults tourl
Usage
Let'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 pageif (res.ok) Router.push("/dashboard")})}, [])React.useEffect(() => {// Prefetch the dashboard page as the user will go there after the loginRouter.prefetch("/dashboard")}, [])return (<form onSubmit={handleSubmit}>{/* Form fields */}<button type="submit">Login</button></form>)}
Router.events
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 cancelled
beforeHistoryChange(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 page
Here
url
is the URL shown in the browser. If you callRouter.push(url, as)
(or similar), then the value ofurl
will 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)}}, [])
Router.beforePopState
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 = asreturn false}return true})
Router.beforePopState(cb: () => boolean)
cb
- The function to run on incomingpopstate
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 apage
as
:String
- the url that will be shown in the browseroptions
:Object
- Additional options sent by Router.push
If 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.