React Router NavBar example with NavLinks

In this example we improve the NavBar, pulling it out into it's own file and using React Router's NavLink component. We've also added styled-components and show how you can restyle React Router's NavLink.

NavBar implementation with Flexbox

To start, we'll declare an outer container NavBarOuterContainer with some vertical margin. Inside this component, we'll add a component called NavBarInner which will be using Flexbox by declaring display: flex.

Inside the NavBarInner, we'll add two top-level components representing a list of NavLinks on the left and on the right. On the left, we declare LeftNav with flex-grow: 1, meaning it will stretch the entire width that it can. This will allow us to fill as many items in the left nav as we want, and still stretch the entire width to leave a space between itself and the right nav item (just one NavItem on the right).

Additionally, we declare the LeftNav a flexbox with display: flex as well, so that we can stack items horizontally. Inside of the LeftNav, we target any NavItem and add a margin-right: 10px to it, so only LeftNav items will have margin on the right, which gives some padding between LeftNav items. We're not adding additional items to the right nav, so we just use a single NavItem as the second top-level navigation link, and that will suffice for now.

Let's discuss the NavItem component.

The NavLink Component

The NavLink is similar to React Router's Link component except that it adds a special class active when the current location matches the path of the Link. This is useful for when you want to add styling on a navigation link to indicate the user is on the current path.

A CSS Class selector with Styled-components

Take a look at the NavItem component that we declare by wrapping React Router's NavLink with the styled helper from styled-components. Observe that we declare two props first to override the browser's default link styles (a blue text color and underline).

We then declare a selector when &.active, meaning when the component has a CSS class of active, apply the styles below. We apply a border-bottom of 1px solid black in this case.

End prop

You may notice that the Home link has an additional prop of end. If the end prop is used, it will ensure this component isn't matched as "active" when its descendant paths are matched. Without this prop, Home link will always think it is matching the other paths.

Menu
Lesson 2/26
import styled from "styled-components";
import { NavLink } from "react-router-dom";

const NavBarOuterContainer = styled.div`
  margin: 20px auto; 
`;

const NavBarInner = styled.div`
  display: flex;
`;

const NavItem = styled(NavLink)`
  text-decoration: none;
  color: black; 

  &.active {
    border-bottom: 1px solid black; 
  }
`;

const LeftNav = styled.div`
  flex-grow: 1;
  display: flex;

  ${NavItem} {
    margin-right: 10px;
  }
`;

function NavBar() {
  return (
    <NavBarOuterContainer>
      <NavBarInner>
        <LeftNav>
          <NavItem to="/" end>
            Home
          </NavItem>
          <NavItem to="missions">Missions</NavItem>
          <NavItem to="logs">Logs</NavItem>
        </LeftNav>
        <NavItem to="account">Account</NavItem>
      </NavBarInner>
    </NavBarOuterContainer>
  );
}

export default NavBar;