I have a list of navlinks. When I'm on a certain page, that navlink should be highlighted. I also want the page up (only) one level to have its navlink highlighted as well, so:
All pages: /blogs, blogs/careers, blogs/authors
Page: /blogs/author Highlight: /blogs/author, /blogs
Page: /blogs/author/Lauren-Stephenson Highlight: /blogs/author/Lauren-Stephenson, blogs/authors Here's how I'm doing it:
import React from 'react';
const navlinks = ["/blogs", "blogs/careers", "blogs/authors"]
const currentPath = "/blogs/authors/Lauren-Stephenson"
export function App(props) {
return (
<div className='App'>
{navlinks.map((links) =>
<div style={{color: currentPath.includes(links) ? 'green' : 'white'}}>{links}</div>
)}
</div>
);
}
But my code not only highlights /blogs/Authors/, it also highlights /blogs, which is incorrect, because I only want the page up one level to be highlighted.
How can I do this?
currentPage: /blogs/Authors/Lauren-Steph
/blogs (HIGHLIGHTED) INCORRECTLY HIGHLIGHTED!
/blogs/careers
/blogs/authors (HIGHLIGHTED) Correct
currentPage: /blogs/Authors
/blogs
/blogs/careers
/blogs/authors (Correct)
currentPage: /blogs
/blogs (Correct)
/blogs/careers
/blogs/authors
CodePudding user response:
You got it the other way around. It's called: Array.protoype.includes() - Notice the "Array". Therefore use an Array:
links.includes(currentPath)
But... given your currentPath
is somewhat a longer path string, you might want additionally check for if some of the navlinks
startsWith a specific String:
const navlinks = ["/blogs", "/blogs/careers", "/blogs/authors"];
const checkNavPath = (path) => navlinks.some(nav => path.startsWith(nav));
console.log(checkNavPath("/blogs"));
console.log(checkNavPath("/blogs/authors"));
console.log(checkNavPath("/blogs/authors/Lauren-Stephenson"));
console.log(checkNavPath("/recipes/food/mashed-potato"));
Also, make sure your paths start all with /
CodePudding user response:
The easiest way is to check if the path starts with the link and the link only has one extra "/".
Since you don't have proper data (not all of the links/paths start with "/") I had to write a function to normalize them.
const navlinks = ["/blogs", "blogs/careers", "blogs/authors"];
const normalizePath = (path) => path.replace(/^(?!\/)/, "/"); // add the starting "/" if it isn't there
const shouldHighlightLink = (currentPath, link) => {
currentPath = normalizePath(currentPath);
link = normalizePath(link);
return currentPath === link ||
(currentPath.startsWith(link "/") &&
currentPath.split("/").length - 1 === link.split("/").length);
}
console.log(
"/blogs/authors/Lauren-Stephenson",
navlinks.reduce((acc, cur) => (
acc[normalizePath(cur)] = shouldHighlightLink("/blogs/authors/Lauren-Stephenson",
cur
), acc), {})
);
console.log(
"/blogs/authors",
navlinks.reduce((acc, cur) => (
acc[normalizePath(cur)] = shouldHighlightLink("/blogs/authors",
cur
), acc), {})
);
CodePudding user response:
So your highlighting logic seems to be: highlight:
- current page
- page one level above
Provided that link formats are consistent using absolute path, you can explicitly check against the 2 paths that should match instead of using string .includes()
const navLinks = ['/blog', '/blog/parent', '/blog/parent/child', '/blog/parent/child/grandchild', '/blog/parent/sibling', '/blog/other', '/blog/other/subpage']
const currentPath = '/blog/parent/child/grandchild'
const getHighlightedPaths = (currentPath) => {
return [
currentPath,
currentPath.substring(0, currentPath.lastIndexOf('/'))
]
}
const highlightedPaths = getHighlightedPaths(currentPath)
console.log('1. ', highlightedPaths)
console.log('2. Should highlight paths?', navLinks.map(link => link ' - ' (highlightedPaths.includes(link) ? 'yes' : 'no')))
Console output:
1. [
"/blog/parent/child/grandchild",
"/blog/parent/child"
]
2. Should highlight paths? [
"/blog - no",
"/blog/parent - no",
"/blog/parent/child - yes",
"/blog/parent/child/grandchild - yes",
"/blog/parent/sibling - no",
"/blog/other - no",
"/blog/other/subpage - no"
]