use-next-route v1.0.0
use-next-route
React hook to create a route link
import { useRoute } from 'use-next-route'
function Page() {
const { href, onClick } = useRoute('/projects')
return (
<a href={href} onClick={onClick}>Click me!</a>
)
}
// <a href="/dashboard/projects">Go to projects</a>Why
As a Next app grows it becomes hard to manage link to all of the different routes. The next/link component has an awkward API, so you end up dropping down to use the singleton next/router in most cases. The router and link also don't have a concept of a "prefix", which is required when mounting a Next app in a sub-directory.
Setup
You'll need to use RouteContext to provide the router and an optional routePrefix to the React app.
import { RouteProvider } from 'use-next-route'
import { withRouter } from 'next/router'
function ProjectsPage(props) {
return (
<RouteProvider route={props.router.route} routePrefix="/dashboard">
<div>My Projects</div>
</RouteProvider>
)
}
export default withRouter(ProjectsPage)You'll most likely want to create a custom _app rather than doing this on every page.
Sub-directory routing
You can use the routePrefix prop to automatically as a prefix to all links. This will be provided as the as option to the router. You'll want to use this if you're mounting your Next app on a sub-directory, like https://myapp.com/dashboard.
This is similar to the assetPrefix option.
API
import {
RouteOptions,
Route,
useRoute,
useRouteContext,
RouteProvider,
} from 'use-next-routes'useRoute(route: UrlObject | string, options: RouteOptions)
Returns an object with the following properties:
href: URL string for the route. Usually used for adding ahrefattribute to links.onClick: This will navigate to the route and handle preventing the default mouse event if needed.isActive: If the current browser location starts with thehref. Used for active states.navigate: Navigate to the route.
You won't use next/link or next/router directly anymore. Instead you can use the hooks.
- Buttons: You can use the
onClickproperty - Links: You can use the
hrefproperty and theonClickproperty. Thehrefwill make it a valid HTML link, allowing users to open to the link in a new tab/window and making it crawlable. Adding theonClickprop will trigger aRouter.pushfor you automatically.
UrlObject
pathname: Absolute path to the Next routequery: Object of key/value pairs that will be appended to the url as a query string.
RouteOptions
prefetch: Prefetch the route. This is disabled by default so you need to opt-inreplace: Usesreplaceinstead ofpush.as: Allows you to override the url in the location bar. If you're usingroutePrefixthis is taken care of for you, but if you want to use a custom alias you can instead. TheroutePrefixwill still be applied.
Examples:
import { useRoute } from 'use-next-route'
function Page() {
const { href, onClick } = useRoute('/projects')
return (
<a href={href} onClick={onClick}>Click me!</a>
)
}
export default ProjectPageEnabling prefetch and replacing instead:
import { useRoute } from 'use-next-route'
function Page() {
const { href, onClick } = useRoute('/projects', {
prefetch: true,
replace: true
})
return (
<a href={href} onClick={onClick}>Click me!</a>
)
}
export default ProjectPageUsing a UrlObject like when you use Router.push:
import { useRoute } from 'use-next-route'
function ProjectPage(props) {
const projectRoute = useRoute({
pathname: '/project/details',
query: {
id: props.project.id
}
})
return (
<a href={projectRoute.href} onClick={projectRoute.onClick}>{props.project.name}</a>
)
}
export default ProjectPageUsing a custom hook:
import { useRoute } from 'use-next-route'
function useProjectRoute(projectId: string) {
return useRoute({
pathname: '/project/details',
query: {
id: projectId
}
})
}
function ProjectPage(props) {
const projectRoute = useProjectRoute(props.project.id)
return (
<a href={projectRoute.href} onClick={projectRoute.onClick}>{props.project.name}</a>
)
}
export default ProjectPageYou can also provide some options
RouteProvider
Add the context to you app to inject the Next router. This is required for useRoute to work.
import { RouteProvider } from 'use-next-route'
import { withRouter } from 'next/router'
function ProjectsPage(props) {
return (
<RouteProvider route={props.router.route} routePrefix="/dashboard">
<div>My Projects</div>
</RouteProvider>
)
}
export default withRouter(ProjectsPage)Patterns
Centralized routes
You can create hooks for specific pages in your app so you're not creating the same routes everywhere:
import { RouteOptions, useRoute } from 'use-next-route'
export function useProjectRoute(id, options?: RouteOptions) {
const route = {
pathname: '/projects',
query: {
id
}
}
return useRoute(route, options)
}
export function useSettingsRoute(options?: RouteOptions) {
return useRoute('/settings', options)
}Then you can use the route in any component:
import { useProjectRoute } from './routes'
function Page({ project }) {
const { href, onClick, isActive } = useProjectRoute(project.id)
return (
<a href={href} onClick={onClick}>{project.name}</a>
)
}7 years ago