< Previous: Time for some Basic User Interface Polish   Next: The First 80% is Done: Now What? >

Adding React Router Breadcrumbs with Link and IndexLink

Those few CSS rules will immediately make our pages look a bit smarter, but I also want to add some very basic breadcrumbs so users can navigate back to the home page more easily.

There are several different ways of doing this, not least using the marvellous React-Breadcrumbs component. But for the sake of simplicity – and also to show you a little bit more React Router magic – we're going to take the most basic approach imaginable: we're going to have each page print out its breadcrumbs.

In order to have these breadcrumb links work correctly, you're going to need to ensure this import line is present in List.js, Detail.js, and User.js:

src/pages/List.js, src/pages/Detail.js, src/pages/User.js

import { IndexLink, Link } from 'react-router';

You've seen the <Link> component before, but now we're adding <IndexLink> into the mix. You'll see why in just a moment!

We're going to start by adding breadcrumbs to the Detail component. Modify the last part of its render() method to this:

src/pages/Detail.js

return (<div>
    <p>You are here: <IndexLink to="/" activeClassName="active">Home</IndexLink>
    > {this.props.params.repo}</p>

    <button onClick={this.selectMode.bind(this, 'commits')}>Show Commits</button>
    <button onClick={this.selectMode.bind(this, 'forks')}>Show Forks</button>
    <button onClick={this.selectMode.bind(this, 'pulls')}>Show Pulls</button>
    {content}
</div>);

Only the "You are here" line is new, but immediately you'll see I'm using that new <IndexLink> component. If you save your page and navigate to a repository you should see something like "You are here: Home > react" in the breadcrumb bar, and the "Home" text is a link back to the home page. How come it's an <IndexLink> rather than a regular <Link>, then?

Well, to find out, just try changing <IndexLink to="/" activeClassName="active">Home</IndexLink> to <Link to="/" activeClassName="active">Home</Link> and see for yourself what happens. Tried it? Yup: the link goes black rather than blue.

This is the "little bit more React Router magic" I mentioned earlier: React Router knows which route is active, and will automatically adjust any <Link> components it finds so that active links automatically have a CSS class of your choosing attached to them.

To see how this works you need to look at this piece of CSS we used in style.css a few minutes ago:

dist/style.css

a.active {
    color: black;
}

And now look at our breadcrumbs code again:

src/pages/Detail.js

You are here: <IndexLink to="/" activeClassName="active">Home</IndexLink>
> {this.props.params.repo}

So, that CSS specifies a style for <a> elements that have the class name active. Then the <IndexLink> component has an activeClassName attribute set to active. This means that when React detects this link is currently being viewed, it will automatically apply the active class to the link.

But there's a problem: all our URLs start with / because it's right there at the base of our routes. When configuring our routes we created a special <IndexRoute> to handle this situation, but a regular <Link> component doesn't take that into account. If you want to say "consider / active only when we're on the List page", you need to use <IndexLink> to match the link to the <IndexRoute> we defined.

The simple rule is this: if you're pointing to the index route of your site, you need to use an index link.

Now that you know the difference between <Link> and <IndexLink> we just need to add breadcrumbs to the List and User components.

The List component already has a message saying "Please choose a repository from the list below", so all you need to do is add the breadcrumbs before that:

src/pages/List.js

<p>You are here: <IndexLink to="/" activeClassName="active">Home</IndexLink></p>

The User component is a little more difficult because its root JSX element is <ul>. We need to wrap that in a <div> so that we can include the breadcrumbs in its output. For the avoidance of doubt, the new render() method should look like this:

src/pages/User.js

render() {
    return (<div>
        <p>You are here:
        <IndexLink to="/" activeClassName="active">Home</IndexLink>
        > {this.props.params.user}</p>
        <ul>
        {this.state.events.map((event, index) => {
            const eventType = event.type;
            const repoName = event.repo.name;
            const creationDate = event.created_at;

            return (<li key={index}><strong>{repoName}</strong>: {eventType}
                at {creationDate}.
            </li>);
        })}
        </ul>
    </div>);
}

That's it – breadcrumbs all done!

Buy the book for $10

Get the complete, unabridged Hacking with React e-book and take your learning to the next level - includes a 45-day no questions asked money back guarantee!

If this was helpful, please take a moment to tell others about Hacking with React by tweeting about it!

< Previous: Time for some Basic User Interface Polish   Next: The First 80% is Done: Now What? >

Copyright ©2016 Paul Hudson. Follow me: @twostraws.