Changing image color in NavLink button React - reactjs

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.

Related

NavLink component stays active? [duplicate]

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.

How to fix unexpected behavior of Next/Link when it is a child of a button?

I am experiencing some issues with next/link when I use it in my app.
I have a reusable component that renders a button. This component is used twice on the page with different urls each time.
When the page is in desktop view, the button works perfectly. I can navigate from one page to another. When I reduce the size of the screen to either tablet or mobile one redirects correctly and the other one does not respond as expected.
To work around the issue I have enclosed the area inside a link so the user can click outside the button area and still be directed to the page but it is not really the experience I want to offer to the user.
I never had this before. Can someone tell me how to fix this or why is it behaving this way, please? thanks.
const Banner = ({
purpose,
imageUrl,
title1,
title2,
desc1,
linkName,
buttonText,
}) => {
return (
<div className="row flex-lg-row-reverse align-items-center g-5 justify-content-center">
<div className=" col-10 col-sm-8 col-lg-6">
<Image
className="d-block img-fluid mx-lg-auto"
src={imageUrl}
width={700}
height={500}
alt="banner"
loader={myLoader}
/>
</div>
<Link href={linkName} passHref>
<div className="col-lg-4 p-3 text-center text-lg-start border-0">
<h1 className="display-6 fw-bold lh-1 mb-3">{purpose}</h1>
<p className="lead">
{title1}
<br /> {title2}
</p>
<p className="lead">{desc1}</p>
<button className="btn link btn-primary btn-xl w-100">
<Link href={linkName} passHref>
<a> {buttonText}</a>
</Link>
</button>
</div>
</Link>
</div>
);
};
export default function Home({ data }) {
const {
results: {
client: { secondhandListing },
},
} = data;
//console.log('index page results',secondhandListing);
return (
<>
<div
data-spy="scroll"
data-bs-target="main-nav"
data-offset="0"
className="scrollspy-example"
tabIndex="0"
>
<Services />
<div className="section d-flex justify-content-center my-5">
<h1 className="my-5" id="#scrollspyHeading2">
Properties
</h1>
</div>
<div className="container-fluid d-flex justify-content-xxl-between align-items-center flex-wrap flex-lg-nowrap">
<div className="section d-flex">
<Banner
purpose="Rent a Home"
title1="Rental Homes for"
title2="Everyone"
desc1="Explore Apartments, Villas, Homes"
desc2="and more"
buttonText="Explore Renting"
linkName="/search?operationType=rent"
imageUrl="https://bayut-production.s3.eu-central-1.amazonaws.com/image/145426814/33973352624c48628e41f2ec460faba4"
/>
</div>
<div className="section d-flex">
<Banner
purpose="Buy a Home"
title1="Find, Buy & Own"
title2="Your Dream Home"
desc1="Explore Apartments, Villas, Homes"
desc2="and more"
buttonText="Explore Buying"
linkName="/search?operationType=sale"
imageUrl="https://bayut-production.s3.eu-central-1.amazonaws.com/image/145426814/33973352624c48628e41f2ec460faba4"
/>
</div>
</div>
<Team />
<Contact />
</div>
</>
);
}
Run the new-link codemod to automatically upgrade previous versions of Next.js to the new <Link> usage:
npx #next/codemod new-link .
This will change <Link><a id="link">Home<a></Link> to <Link id="link">Home</Link>.
Alternatively, you can add the legacyBehavior prop <Link legacyBehavior><a id="link">Home<a></Link>.
<button> and <a> do not allow interactive content to be their content.
That said, you're passing invalid children to your <Link> component and to the <button> element:
<Link href={linkName} passHref>
<div className="col-lg-4 p-3 text-center text-lg-start border-0">
<h1 className="display-6 fw-bold lh-1 mb-3">{purpose}</h1>
<p className="lead">{title1}<br /> {title2}</p>
<p className="lead">{desc1}</p>
{/* Invalid child */}
<button className="btn link btn-primary btn-xl w-100">
{/* Invalid child */}
<Link href={linkName} passHref>
<a> {buttonText}</a>
</Link>
</button>
</div>
</Link>
That may be the reason of why your component is behaving oddly.
PS. Formatting your code helps by making it more readable. :). You can do that by setting ESLint and Prettier up.
You maybe need to add the legacyBehavior as props in the next/link component.
import Link from 'next/link'
function Legacy() {
return (
<Link href="/about" legacyBehavior>
<a>About Us</a>
</Link>
)
}
export default Legacy
docs: https://nextjs.org/docs/api-reference/next/link#if-the-child-is-a-tag

React Ternary Operator Prevent Repeating Code with Styled components?

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>

Visual Studio Code with React how to see usage of Component or Function

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".

Toggling Images for Active Links with React.js

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>
.....

Resources