Reputation: 117
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
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