This question already has answers here:
React Router Dom v6 shows active for index as well as other subroutes
(2 answers)
Closed 5 months ago.
A navlink to homepage always stays active. Other 2 navlinks work correctly and only added an active style when chosen. Is there any problem with routes or function that changes the active link?
const activeStyles = {
color: 'green',
};
<ul className="flex gap-8">
<li>
<NavLink
to={"/"}
className="text-xs text-gray-400 hover:text-white"
style={({ isActive }) => (isActive ? activeStyles : undefined)}
>
Main
</NavLink>
</li>
<li>
<NavLink
to={"posts"}
className="text-xs text-gray-400 hover:text-white"
style={({ isActive }) => (isActive ? activeStyles : undefined)}
>
My Posts
</NavLink>
</li>
<li>
<NavLink
to={"new"}
className="text-xs text-gray-400 hover:text-white"
style={({ isActive }) => (isActive ? activeStyles : undefined)}
>
Add post
</NavLink>
</li>
</ul>
For react-router v6, if you want your root route ("/") to be active only at this route, you should add an end prop to <NavLink>:
<NavLink to="/" end>
Main
</NavLink>
For this you have to use exact key work in Navlink like this:
<NavLink to='/' exact={true}>
Main
</NavLink>
because'/' is active for all routes that's why you are getting this.
Related
So I'm using styled components and found the only way to trigger my function is with a ternary operator that wraps my entire navbar component. The problem is I have to recopy the entire component code into the : statement which basically means I'm writing my nav component code twice just to get the ternary to work properly.
Is there a way to not repeat it and write the ternary with the least amount of code?
So here's my code issue
return (
<>
// If scroll is true, I want to add this active prop onto my <Nav>
{scroll ? (
<Nav active click={click}>
<NavbarContainer>
<NavLogo to="/" onClick={closeMobileMenu}>
<NavIcon />
EXPLOR
</NavLogo>
<MobileIcon onClick={handleClick}>
{click ? <FaTimes /> : <FaBars />}
</MobileIcon>
<NavMenu onClick={handleClick} click={click}>
<NavItem>
<NavLinks to="/">Home</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/images">Images</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/products">Products</NavLinks>
</NavItem>
</Nav>
:
// If the scroll is false, I remove the active prop from my nav
(
<Nav click={click}>
<NavbarContainer>
<NavLogo to="/" onClick={closeMobileMenu}>
<NavIcon />
EXPLOR
</NavLogo>
<MobileIcon onClick={handleClick}>
{click ? <FaTimes /> : <FaBars />}
</MobileIcon>
<NavMenu onClick={handleClick} click={click}>
<NavItem>
<NavLinks to="/">Home</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/images">Images</NavLinks>
</NavItem>
<NavItem>
<NavLinks to="/products">Products</NavLinks>
</NavItem>
</Nav>
}
</>
The whole point is so I can trigger this active prop from my styled component
background: ${({ active }) => (active ? "#141414" : "transparent")};
But as you can see I had to copy my entire component code twice because the <Nav> that has the active prop wraps around my entire code.
Is there an easier way to toggle the active prop with styled components without having to recopy my entire navbar in the : or statement?
Assuming active is a booelan you can smply set active={scroll } like so
<Nav active={scroll} click={click}>
.....
</Nav>
Simply see who is using a Component or Function.
Let's say I have this in the file called Menu .js:
const Menu = () => {
return (
<>
<div className="logo-container">
<SVG className="brand-logo" src={photoLogo}/>
</div>
<nav className="nav-wrapper">
<ul className="menu-links-group">
<li className="menu-link"><NavLink exact activeClassName="activeLink" to="/">Home</NavLink></li>
<li className="menu-link"><NavLink exact activeClassName="activeLink" to="/about">About Greta</NavLink></li>
<li className="menu-link"><NavLink exact activeClassName="activeLink" to="/portfolio">FFF</NavLink></li>
<li className="menu-link"><NavLink exact activeClassName="activeLink" to="/contact">Contact</NavLink></li>
</ul>
</nav>
<div className="media-container">
<FontAwesomeIcon icon={faInstagram} className="font-awesome-icon" ></FontAwesomeIcon>
<FontAwesomeIcon icon={faLinkedin} className="font-awesome-icon" ></FontAwesomeIcon>
<FontAwesomeIcon icon={faFacebook} className="font-awesome-icon" ></FontAwesomeIcon>
</div>
</>
)
}
export default Menu
How do I quickly find all usages of this Menu? Maybe there is some VCode plugin?
Right click on Menu and select "Find All References".
I am wonder how to change image when NavLink is active.
So far I wrote this :
<li className={(active==='adminPanel') ? styles.LeftMenuActiveLink : null }
onClick={()=>changeActive('adminPanel')}
style={{color: '#69B4D6'}}>
<NavLink to="/adminPanel">
<img
src={(active==='adminPanel')? NotificationsImageActive : NotificationsImage}
alt="notification icon" width="60px" height="60px" />
<span >Panel Admina</span>
</NavLink>
</li>
where active variable is in my state. This works, but refreshing page destroy it. I am wonder if I can check somehow if NavLink is active and with this information set my src in <img />
Working version :
<li>
<NavLink onClick={() => setPath("/events")} activeClassName={styles.LoggedLeftMenuActiveLink} to="/events">
<img
src={(window.location.pathname === "/events") ? EventsImageActive : EventsImage}
alt="events icon" width="60px" height="60px" />
Wydarzenia
</NavLink>
</li>
You can check something like
location.pathname == "adminPanel"
so it will work even when your page is reloaded/refreshed.
I am currently trying to learn React.js for a school project and am having trouble with toggling images in combination with active links (I have searched high and low for a tutorial with no avail). My site is going to look similar to the old time Kingdom Hearts 1 menu theme; the Navbar looks like the following image.
As shown in the above image, the home page is hard-coded to be "active." What I need help with is making each link appear in this "active" state when selected/active. When a user clicks on one of the NavLinks, the image should go from grey to black/orange. When a link is not selected (or inactive), the image should go from black/orange back to grey. Active/selected links should also have black text while inactive links have grey. So far, all I have found out is how to toggle a singular class but not multiple. Overall, I really don't know how to go about this at all. How do I toggle one NavLink active and change its image while also changing all other NavLinks to inactive, changing their images as well? Any help would be much appreciated. I have the following code for my Navbar so far:
export class NavMenu extends Component {
static displayName = NavMenu.name;
constructor(props) {
super(props);
this.toggleNavbar = this.toggleNavbar.bind(this);
this.state = {
collapsed: true
};
}
toggleNavbar() {
this.setState({
collapsed: !this.state.collapsed
});
}
render() {
return (
<Navbar
fixed="bottom"
className="navbar-expand-sm navbar-toggleable-sm ng-white border-top mb-3"
light
>
<NavbarToggler onClick={this.toggleNavbar} className="mr-2" />
<Collapse
className="d-sm-inline-flex flex-sm-row-reverse"
isOpen={!this.state.collapsed}
navbar
>
<ul className="navbar-nav mr-auto">
<NavItem>
<NavLink
tag={Link}
id="navHome"
className="text-dark active"
to="/"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
hidden
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
/>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink
tag={Link}
d="navResume"
className="text-dark inactive"
to="/resume"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
hidden
/>
Resume
</NavLink>
</NavItem>
<NavItem>
<NavLink
tag={Link}
d="navContact"
className="text-dark inactive"
to="/contact"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
hidden
/>
Contact
</NavLink>
</NavItem>
<NavItem>
<NavLink
tag={Link}
d="navFetch"
className="text-dark inactive"
to="/fetch-data"
>
<img
src="/Images/NLUnactiveImg.png"
alt="Unactive Link Image"
height="45"
width="45"
/>
<img
src="/Images/NLActiveImg.png"
alt="Active Link Image"
height="45"
width="45"
hidden
/>
Fetch data
</NavLink>
</NavItem>
</ul>
</Collapse>
<div>
{' '}
<PlaySound child={this.state.child} />{' '}
</div>
</Navbar>
);
}
}
First of all remove you css (images) into a seperate css file. Make a class and put your css into that. Something like this
<NavLink tag={Link} d="navResume" className="text-dark inactive resumeImage" to="/resume">
Resume
</NavLink>;
in your css file
.resumeImage {
//declare your image styles here
}
Repeat above for all your Navlinks.
Now keep those styles which you only want to apply to the active link in a seperate class and apply that class to all the Navlinks like below
<NavLink
tag={Link}
d="navResume"
className="text-dark inactive resumeImage"
activeClassName="activestyleclass"
to="/resume"
>
Resume
</NavLink>;
You can check the current URL and change the image based on the url since active class should be depend on the url too.
You can use react hook useLocation to get current URL.
import { useLocation } from 'react-router-dom';
const Component= () => {
const [pathname, setPathname] = useState('/');
const location = useLocation();
useEffect(() => {
setPathname(location.pathname);
}, [location]);
return (
<nav className="navbar">
<NavLink to="/" className="navbar-item">
{pathname === '/' ? (
<img src="/images/navbar/home_active.png" alt="Home" />
) : (
<img src="/images/navbar/home.png" alt="Home" />
)}
</NavLink>
.....
I have a NavLink which have child components
<NavLink
className={StyledAppNavItem}
activeClassName={StyledAppNavItemActive}
to={link.path}
>
<Icon size={28} icon={link.icon} color={isActive?'red':'blue'}/>
<StyledAppNavName>{link.name}</StyledAppNavName>
</NavLink>
Like activeClassName is attached when the link is active, I need to detect if this link is active and send a prop to its child component Icon
Somewhat like <Icon color={linkisActive?'red':'blue'}/>
Unfortunately, there is no way to get isActive from NavLink. You need to create your custom NavLink. Something like this:
function MyNavLink() {
return (
<Route path={link.path} children={({ match }) => (
<Link
className={`${StyledAppNavItem} ${match ? StyledAppNavItemActive : ''}`}
to={link.path}
>
<Icon size={28} icon={link.icon} color={match ? 'red' : 'blue'}/>
<StyledAppNavName>{link.name}</StyledAppNavName>
</Link>
)} />
);
}
Or you can just add Route to your current component:
<NavLink
className={StyledAppNavItem}
activeClassName={StyledAppNavItemActive}
to={link.path}
>
<Route path={link.path} children={({ match }) => (
<Icon size={28} icon={link.icon} color={match?'red':'blue'}/>
)} />
<StyledAppNavName>{link.name}</StyledAppNavName>
</NavLink>