React Router Breadcrumbs HOC
Just a tiny, flexible, higher order component for rendering breadcrumbs with react-router 4.x
site.com/user/id → user / John Doe
Description
Deconstruct a route and return matching breadcrumb components you can render however you like. Render a simple string, a component that fetches a model in order to display the desired content, or just render something totally unrelated to the route.
We are currently using this method @ Koan Inc.
Install
yarn add react-router-breadcrumbs-hoc
or
npm install react-router-breadcrumbs-hoc --save
Usage
withBreadcrumbs(routeConfigObject)(MyComponent);
Example
import React from 'react';
import { NavLink } from 'react-router-dom';
import { withBreadcrumbs } from 'react-router-breadcrumbs-hoc';
const UserBreadcrumb = ({ match }) =>
<span>{match.params.userId}</span>;
const routes = [
{ path: '/', breadcrumb: 'Home' },
{ path: '/users', breadcrumb: 'Users' },
{ path: '/users/:userId', breadcrumb: UserBreadcrumb },
{ path: '/something-else', breadcrumb: ':)' },
];
const Breadcrumbs = ({ breadcrumbs }) => (
<div>
{breadcrumbs.map(({ breadcrumb, path, match }) => (
<span key={path}>
<NavLink to={match.url}>
{breadcrumb}
</NavLink>
<span>/</span>
</span>
))}
</div>
);
export default withBreadcrumbs(routes)(Breadcrumbs);
For the above example...
Pathname | Result |
---|
/users | Home / Users |
/users/id | Home / Users / John |
/something-else | Home / :) |
Already using a route config array with react-router?
Simple! Just add a breadcrumbs
prop to your routes that require breadcrumbs.
API
Route = {
path: String
breadcrumb: String|Function
matchOptions?: Object
}
Breadcrumb = {
path: String
match: String
breadcrumb: Component
}
Location = {
key: String
pathname: String
search: String
hash: String
state: Object
}
withBreadcrumbs(routes: Array<Route>): HigherOrderComponent
getBreadcrumbs({ routes: Array<Route>, location: Location }): Array<Breadcrumb>
Order Matters!
Consider the following route config:
[
{ path: '/users', breadcrumb: 'Users' },
{ path: '/users/:id', breadcrumb: 'Users - id' },
{ path: '/users/create', breadcrumb: 'Users - create' },
]
This package acts like a switch statement and matches the first breadcrumb it can find. So, unfortunately, visiting /users/create
will result in the Users > Users - id
breadcrumbs instead of the desired Users > Users - create
breadcrumbs.
To get the right breadcrumbs, simply change the order:
[
{ path: '/users', breadcrumb: 'Users' },
{ path: '/users/create', breadcrumb: 'Users - create' },
{ path: '/users/:id', breadcrumb: 'Users - id' },
]
Now, /users/create
will match the create breadcrumb first, and all others will fall through to /:id
.
Dynamic Breadcrumbs
React Router's location object let's you pass state
property. Using the state
allows one to update the Breadcrumb to display dynamic info at runtime. Consider this example:
const Breadcrumb = ({location: { state: { isNew } } }) => {
return <span>{isNew ? 'Add New' : 'Update'}</span>
}
{
pathname: '/editor',
breadcrumb: Breadcrumb
...
}
<Link to={{pathname: '/editor'}}>Edit</Link>} // Upon navigation, breadcrumb will display: Update
<Link to={{pathname: '/editor', state: {isNew: true}}}>Add</Link>} // Upon navigation, breadcrumb will display: Add New
Now based on what you pass in the state
prop, the Breadcrumb will display dynamic values at runtime!