Rendering nav links with .map() in React.

June 23rd, 2020 · 5 min read

React utilises .map() to render items in a list, this can be great for dynamically adding links to our navigation. Instead of copying the markup, again and again, ill run through how I have used .map() on my navigation.

If you don't know already my site is built on Gatsby a static site generator built on React. Gatsby’s <Link> component enables linking to internal pages as well as a powerful performance feature called preloading.

In any situation where you want to link between pages on the same site, use the Link component instead of an a tag.

// standard a tag
<a href="/posts">Posts</Link>

// Gatsby Link component
<Link to="/posts">Posts</Link>

The basis of our navigation

Let's start off by creating the foundation of our component.

import React from 'react'
import { Link } from 'gatsby'

const Nav = () => {
	
	return()
}

export default Nav

Styling our links

Now we have everything set up we can now add an object called styles this will allow us to use className and activeClassName

It’s often a good idea to show which page is currently being viewed by visually changing the link matching the current page. This can be done by using activeClassName — a class name that will only be added to the Link when the current item is active.

As I am using TailWind here, my styles object is going to look like this:

const styles = {
        className:'text-gray-600 block px-2 py-1 hover:underline hover:text-gray-900',
        activeClassName: 'underline text-gray-900'
    }

We can then access those properties by dot notation as follows:

styles.className
styles.activeClassName

Generating Link data.

Now we have our styles in an object, we can now move on to the Link data we want to pass. This will be an array of objects allowing us to use .map() on the array.

const links = [
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/projects',
            name: 'Projects'
        },
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/posts',
            name: 'Posts'
        },
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/contact',
            name: 'Contact'
        },
    ]

Above each object has 4 key pairings.

  • className: Our link styles
  • activeClassName: Our styles for active links
  • to: The page we wish to link to once clicked
  • name: What we what our link to display on site

Our navigation component should now look something like this:

import React from 'react'
import { Link } from 'gatsby'

const Nav = () => {
 
    const styles = {
        className:'text-gray-600 block px-2 py-1 hover:underline hover:text-gray-900',
        activeClassName: 'underline text-gray-900'
    }
    
    
    const links = [
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/projects',
            name: 'Projects'
        },
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/posts',
            name: 'Posts'
        },
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/contact',
            name: 'Contact'
        },
 
    ]

    return ( )
}

export default Nav

Adding our data to our markup.

Within our return statement, we need a parent <div> so lets do that

return(
	<div></div>
)

You can then build out your navigation bar how ever you like the next bit will be how to dynamically display the links. This can be done by using .map() on our links array of objects as below shows:

<div>
	{links.map(link => (<Link className={link.className} activeClassName={link.activeClassName} to={link.to}>{link.name}</Link> ))}
 </div>

When using .map() we have to provide it with a callback function which will be passed every item in the links array.

For the above example, our one required argument for our callback function is link which now allows us to access items on the links array by using dot notation again. If you were to check the Gatsby docs for Link you can see it should look something like this:

<Link className= activeClassName= to= ></Link>

Now this wouldnt do anything so we have to add the following to it so map() can populate it as so:

<Link className={link.className} activeClassName={link.activeClassName} to={link.to}>{link.name}</Link>

If you want to learn more about how map() works you can see that here.

Finished Item

Now we have that in place our navigation component should look like this:

import React from 'react'
import { Link } from 'gatsby'

const Nav = () => {    
  
  const styles = {
        className:'text-gray-600 block px-2 py-1 hover:underline hover:text-gray-900',
        activeClassName: 'underline text-gray-900'
    }    const links = [
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/projects',
            name: 'Projects'
        },
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/posts',
            name: 'Posts'
        },
        {
            className: styles.className,
            activeClassName: styles.activeClassName,
            to: '/contact',
            name: 'Contact'
        },    
    ]    
    
    
    return (
      <div>
          <div>LOGO</div>
          <div>
         {links.map(link => (<Link className={link.className} activeClassName={link.activeClassName} to={link.to}>{link.name}</Link> ))}
         </div>
      </div>
    )
}
export default Nav

Hope this helps. You can see my navigation component here, if you get stuck you can hit me up on Twitter.

Learn more about map

Paul Bennett

Written by Paul Bennett, Self-taught developer based in London.

© 2020 Paul Bennett