Issue
I have a navigation created using React-Router
nav.tsx
import React from 'react'
import { menu } from './menu'
import { Link } from 'react-router-dom'
import styles from './HamburgerMenu.module.scss'
const HamburgerMenu: React.FC = () => {
const [active, setActive] = React.useState<number>(0)
console.log(active)
return (
<nav>
<ul className={styles.menu}>
{menu.map((item, index) => (
<li
onClick={() => setActive(index)}
key={item.title}
className={styles[active === index ? 'active' : '']}
>
<Link to={item.link}>{item.title}</Link>
</li>
))}
</ul>
</nav>
)
}
export default HamburgerMenu
menu.ts:
export const menu: IMenuItem[] = [
{
link: '/',
title: 'главная'
},
{
link: '/profile',
title: 'профиль'
},
{
link: '/discipline',
title: 'наказания'
},
{
link: '/store',
title: 'магазин'
},
{
link: '/statistics',
title: 'статистика'
}
]
main.tsx:
import React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider, createBrowserRouter } from 'react-router-dom'
import Home from './pages/Home/Home'
import './assets/style/global.scss'
import NotFoundPage from './pages/NotFoundPage'
import Profile from './pages/Profile/Profile'
const router = createBrowserRouter([
{
element: <Home />,
path: '/'
},
{
element: <Profile />,
path: '/profile'
},
{
element: <NotFoundPage />,
path: '*'
}
])
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
)
style.scss
.menu {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10;
margin-right: 100px;
li.nav-link-item {
margin: 0px 50px;
a {
color: $white;
opacity: 0.7;
transition: opacity 0.3s ease;
font-size: 20px;
&:hover {
opacity: 1;
}
}
}
li.nav-link-item:has(a.active) {
border-radius: 10px;
border: 5px solid #542c44;
padding: 7px 42px;
}
}
Layout.tsx - the page turns into it
import React from 'react'
import { ILayoutProps } from './Laout.type'
import Header from '../Header/Header'
import Footer from '../Footer/Footer'
import styles from './Layout.module.scss'
const Layout: React.FC<ILayoutProps> = ({ children }) => {
return (
<div className={styles['layout']}>
<Header />
{children}
<Footer />
</div>
)
}
export default Layout
When switching between '/'
and '/profile'
the "active"
class is constantly reset and switched to 0, if I want the "active"
class to be added to '/profile'
, then I need to click on it 2 times, and if I switch between '/discipline'
, '/store'
, '/statistics'
, classes are assigned normally. I understand that this behavior is most likely due to the fact that '/discipline'
, '/store'
, '/statistics'
are not declared pages, but what about '/'
and '/profile'
? Why could this be happening, and how can this be corrected?
Solution
Use the NavLink
component which applies an "active"
classname for the matched link by default, and use CSS to select the li
element with a currently matching link.
Example:
const HamburgerMenu: React.FC = () => {
return (
<nav>
<ul className={styles.menu}>
{menu.map((item, index) => (
<li
key={item.title}
className="nav-link-item" // <-- something easily targetable
>
<NavLink end to={item.link}>
{item.title}
</NavLink>
</li>
))}
</ul>
</nav>
);
};
li.nav-link-item {
/* li styling */
}
li.nav-link-item:has(a.active) {
/* "active" li styling overrides */
}
Information:
Demo
Since you are using SASS, this appears to be correct CSS for what you are working with:
li.nav-link-item {
margin: 0px 50px;
a {
color: #fff;
opacity: 0.7;
transition: opacity 0.3s ease;
font-size: 20px;
&:hover {
opacity: 1;
}
}
&:has(:global(a.active)) { // <-- access global non-SASS "active" class
border-radius: 10px;
border: 5px solid #542c44;
padding: 7px 42px;
}
}
Answered By - Drew Reese
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.