Reputation: 2341
I'm trying to create a navbar where the link of the current page is highlighted. You can see a live example of my attempt here. The correct page is highlighted if you refresh the page, but not from just clicking on a link. I've tried to set my useEffect
params as [window]
[window.location]
and [window.location.href]
and nothing works.
const PageLinks = ({ links, className = "" }) => {
const [urlPath, setUrlPath] = useState("");
useEffect(() => {
setUrlPath(url.parse(window.location.href).pathname);
}, [window]);
return (
<>
{Object.keys(links).map((key) => {
const active = (
urlPath == `/${key}` ||
urlPath == "/" && key == "home"
);
return (
<Link
to={links[key]}
key={key}
>
{key}
</Link>
)
})}
</>
);
};
https://github.com/samgermain/react-boiler-plate
Upvotes: 0
Views: 760
Reputation: 557
There's no need to track the entire window object. You can store the currently selected menu item in a state and then conditionally format menu items, if the specific element equals the one in the state (see code snippet).
To apply the conditional formatting when the user directly navigates to the url instead of clicking one of the items (e.g. changing /home
to /about
), you can use the useLocation hook.
const { useState } = React;
const NavItem = (props) => {
return (
<li><a href="#">
{props.current ? (
<strong>{props.label}</strong>
) : (
<span onClick={props.setSelected}>{props.label}</span>
)}
</a></li>
);
};
const App = () => {
const [currentItem, setCurrentItem] = useState();
const items = ["home", "about", "contact"];
return (
<ul>
{items.map((e) => {
return (
<NavItem
label={e}
setSelected={() => setCurrentItem(e)}
current={currentItem === e}
/>
);
})}
</ul>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 2