Rendering nav links with .map() in React.
Paul Bennett
Posted on June 24, 2020
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
PS: If there is a better way to do navigation in React please let me know.
Posted on June 24, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.