Chris
Chris

Reputation: 117

React Router Navbar depending on route

I am trying to style a Navbar Link depending on the current path in my React App, if the path is /create or /add it should change it's styling. Here is what I have so far in my header component:

          <div
            id="createLink"
            className={this.state.createClassName}
            onClick={() => this.handleModalToggle()}
          >
            CREATE
          </div>

  handleActiveLink= () => {
    let path = this.props.location.pathname
     if (path === "/add" | path === "/create") {
       this.setState({createClassName: "nav-link-active"})
     } else {
       this.setState({ createClassName: "nav-link" })
     }
  };

  componentDidMount() {
    this.handleActiveLink()
  }

This works but only after I refresh the page which makes sense but it's not what I want. So I am looking for a way to change the className before even rendered and get the path first (I am using withRouter from react-router-dom)

Upvotes: 3

Views: 2034

Answers (1)

Drew Reese
Drew Reese

Reputation: 202608

Issue appears to be you only check the path when the component mounts and not when it updates. You should also check in componentDidUpdate

handleActiveLink= () => {
  let path = this.props.location.pathname;
  if (path === "/add" || path === "/create") {
    this.setState({createClassName: "nav-link-active"});
  } else {
    this.setState({ createClassName: "nav-link" });
  }
};

componentDidMount() {
  this.handleActiveLink();
}

componentDidUpdate() {
  this.handleActiveLink();
}

In this case I instead recommend not storing such transient data in state, and simply derive it from the props and set as a className in the render function (or wherever you render it). This way it's computed each render when the UI is going to be updated by something and will always be up-to-date (i.e. you won't need to worry about lifecycle functions).

render() {
  const { location: { pathname } } = this.props;
  const linkClass = ["/add", "/create"].includes(pathname)
    ? "nav-link-active"
    : "nav-link";

  ...

  <div
    id="createLink"
    className={linkClass}
    onClick={() => this.handleModalToggle()}
  >
    CREATE
  </div>
  ...
}

Upvotes: 3

Related Questions