Hover event does not target children - javascript

I have a simple navbar and when a user hovers over a <li> tag it must turn red. When the user removes their cursor it must turn grey. It works but not properly. Inside <li> tags I have <Link> provided by react-router-dom and when I target <li> tag it works properly but when I target <Link> it does not work on parent tag (<li>).
Here is my code:
Navbar.js:
return(
<nav className={this.props.navClass}>
<ul>
<li
className="main"
style={{transitionDuration: "0.9s"}}
onMouseEnter={this.props.mouseEnter}
onMouseLeave={this.props.mouseLeave}
>
<Link to="/">მთავარი</Link>
</li>
<li
className="aboutUs"
>
<Link
to="/about-us"
onMouseEnter={this.props.mouseEnter}
onMouseLeave={this.props.mouseLeave}
>ჩვენს შესახებ</Link></li>
<li
className="contactUs"
onMouseEnter={this.props.mouseEnter}
onMouseLeave={this.props.mouseLeave}
>
<Link to="/contact">დაგვეკონტაქტე</Link>
</li>
</ul>
</nav>
)
Main.js:
hover(e) {
e.preventDefault();
e.target.style.backgroundColor = 'red'
}
mouseLeave(e) {
e.target.style.backgroundColor = 'grey'
}
render() {
return(
<div className="wrapper">
<div className="navBar">
<Navbar
navClass="navbar"
mouseEnter={this.hover.bind(this)}
mouseLeave={this.mouseLeave.bind(this)}
/>
</div>
</div>
)
}
How can I fix it?
By the way, I will be glad if you tell me if I am breaking UI in different components correctly.
Thank you!

you could add link{pointer-events:none} to your css.

First, in the Navbar component you need to wrap up your Links inside Router:
import { BrowserRouter as Router, Link } from "react-router-dom";
return (
<nav className={this.props.navClass}>
<Router>
<ul>
<li className="main" style={{transitionDuration: "0.9s"}} onMouseEnter={this.props.mouseEnter} onMouseLeave={this.props.mouseLeave}>
<Link to="/">მთავარი</Link>
</li>
<li className="aboutUs">
<Link to="/about-us" onMouseEnter={this.props.mouseEnter} onMouseLeave={this.props.mouseLeave}>ჩვენს შესახებ</Link>
</li>
<li className="contactUs" onMouseEnter={this.props.mouseEnter} onMouseLeave={this.props.mouseLeave}>
<Link to="/contact">დაგვეკონტაქტე</Link>
</li>
</ul>
</Router>
</nav>
);
The above code works fine, in the second <li className="aboutUs"></li> the reason that only <Link /> component is highlighted and not its parent (li) is that Link component equivalents to <a></a> and its display is inline.
If you add the following css, the parent li is also highlighted.
a {display: block;}

Related

Why does adding useState result in a white screen in my react app?

The code below works completely fine and results in the image below.
import React from "react";
import "./App.css";
import { useState } from "react";
function App(){
return(
<body>
<div className="nav_bar">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"></link>
<ul className="top">
<div className="circle circle1">
<li className="material-icons noselect">
drag_handle
</li>
</div>
<div className="circle circle2">
<li className="material-icons noselect">
home
</li>
</div>
<div className="circle circle3">
<li className="material-icons noselect">
person_outline
</li>
</div>
</ul>
<nav>
<ul className="bottom">
<li className="material-icons noselect" id="feed-bottom">
drag_handle
</li>
<li className="material-icons noselect" id="home-bottom">
home
</li>
<li className="material-icons noselect" id="profile-bottom">
person_outline
</li>
</ul>
</nav>
</div>
</body>
);
}
export default App;
Result
Adding useState to get and set the current state causes the navbar to disappear and show a completely white screen. Specifically I am using useState to change the icon shown in the nav bar to text and to set the currernt state to the icon that is clicked. Code Below
import React from "react";
import "./App.css";
import { useState } from "react";
function App(){
const[selected, setselected] = useState('home');
if(selected === 'feed'){
const feed = document.getElementById('feed-bottom');
feed.innerHTML = 'FEED';
} else if (selected === 'profile') {
const profile = document.getElementById('profile-bottom');
profile.innerHTML = 'PROFILE';
}else{
const home = document.getElementById('home-bottom');
home.innerHTML = 'HOME';
}
return(
<body>
<div className="nav_bar">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"></link>
<ul className="top">
<div className="circle circle1">
<li className="material-icons noselect">
drag_handle
</li>
</div>
<div className="circle circle2">
<li className="material-icons noselect">
home
</li>
</div>
<div className="circle circle3">
<li className="material-icons noselect">
person_outline
</li>
</div>
</ul>
<nav>
<ul className="bottom">
<li className="material-icons noselect" id="feed-bottom" onClick={setselected('profile')}>
drag_handle
</li>
<li className="material-icons noselect" id="home-bottom" onClick={setselected('home')}>
home
</li>
<li className="material-icons noselect" id="profile-bottom" onClick={setselected('profile')}>
person_outline
</li>
</ul>
</nav>
</div>
</body>
);
}
export default App;
I've looked up many post that refernece similar issues but couldn't find one that pretained to mine. I would grealty appreciate some assitance.
This line
home.innerHTML = 'HOME';
will cause an error on mount, because on mount, the React elements returned from App haven't been returned yet - the container is still empty; the #feed-bottom element doesn't exist yet.
While you could fix it by only assigning if the element actually exists, it would be far better to do it the React way and put the values conditionally into the JSX. Don't use vanilla DOM methods in React unless you absolutely have to.
Another problem is that your listeners - eg onClick={setselected('home')} - run when computed (immediately), because you're invoking the setselected function instead of passing a function as a prop to onClick.
You also probably meant to pass feed in the feed-bottom element (instead of profile).
To implement your logic in the React way, you need something like:
<li className="material-icons noselect" id="feed-bottom" onClick={() => setselected('feed')}>
{ selected === 'feed' ? 'FEED' : 'drag_handle' }
</li>
<li className="material-icons noselect" id="home-bottom" onClick={() => setselected('home')}>
{ selected === 'home' ? 'HOME' : 'home' }
home
</li>
<li className="material-icons noselect" id="profile-bottom" onClick={() => setselected('profile')}>
{ selected === 'profile' ? 'PROFILE' : 'person_outline' }
person_outline
</li>
and remove all of the if(selected === 'feed'){ and the like code from the top.

How do I add a class to a react element when it is clicked

I have this react component and I am trying to create a hamburger menu but, I don't know how to add a class when a button is clicked. I am new to React so please go easy on me. When I run the below code it doesn't work and throws an error in the Chrome dev tools.
function Nav() {
const hamburger = document.getElementById('hamburger');
const navUL = document.getElementById('navul');
hamburger.addEventListener('click', () =>{
navUL.classList.toggle('show');
});
return (
<header>
<h2>
<a href="/">
Travis Helms
</a>
</h2>
<nav>
<ul className="flex-row" id='navul'>
<li className="mx-2">
<a href="#about">
About me
</a>
</li>
<li>
<span>Portfolio</span>
</li>
<li>
<span>Contact</span>
</li>
<li>
<span>Resume</span>
</li>
</ul>
</nav>
<button className="hamburger" id="hamburger">
<FontAwesomeIcon icon={faBars}></FontAwesomeIcon>
</button>
</header>
);
}
First of all, welcome to React! It's an amazing framework!
It would have been more helpful if you provided the error you are getting but from the code you shared I can see there are a few things you need to do differently.
Generally, you can use event listeners in React for certain things, and there is a certain way to add them properly, but for the most part they are not used very frequently. Instead, for example, to assign a click event to an element in React, all you need to do is pass it the onClick attribute with the function you want it to execute when it is clicked, for example <button onClick={doSomething}>click me</button>.
An easy way to control the state of your component is by using the useState hook and toggle the class of an element using state. In your case, it could look like this:
import React, { useState } from 'react';
const Nav = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<header>
<h2>
Travis Helms
</h2>
<nav>
<ul className={"flex-row " + (isOpen ? "show" : "")}>
<li className="mx-2">
About me
</li>
<li>
<span>Portfolio</span>
</li>
<li>
<span>Contact</span>
</li>
<li>
<span>Resume</span>
</li>
</ul>
</nav>
<button
className="hamburger"
onClick={() => setIsOpen(!isOpen)}
>
<FontAwesomeIcon icon={faBars}></FontAwesomeIcon>
</button>
</header>
);
};
It looks like you are in a very early stage of learning React and for you to be successful coding with React you need to cover a few basics like state management, props, children and a few more things. I would recommend going on YouTube and find a good introduction video to React and code along to it! There are a lot of great resources in there for people who are just starting with React, just make sure it's something fairly recent (I'd say 2020 onwards).
Ok. So I went to a tutor and worked with them to come up with this solution to toggle my hamburger menu. Just thought I would add this answer for the benefit of other beginning React programmers.
import React,{ useState } from 'react';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faBars } from '#fortawesome/free-solid-svg-icons';
function Nav(props) {
const [navClass, setnavClass]= useState("flex-row");
const [toggledNav, settoggledNav]= useState(true);
const addClass=() => {
if (toggledNav){
setnavClass("flex-row show");
settoggledNav(false);
}else {
setnavClass("flex-row");
settoggledNav(true);
}
}
return (
<header>
<h2>
<a href="/">
Travis Helms
</a>
</h2>
<nav>
<ul className={navClass} id='navul'>
<li className="mx-2">
<a href="#about">
About me
</a>
</li>
<li>
<span>Portfolio</span>
</li>
<li>
<span onClick={() => props.setmenuSelect(1)}>Contact</span>
</li>
<li>
<span>Resume</span>
</li>
</ul>
</nav>
<button onClick={addClass} className="hamburger" id="hamburger">
<FontAwesomeIcon icon={faBars}></FontAwesomeIcon>
</button>
</header>
);
}
export default Nav;

How to change a <a> tag color when I click on it and it doesn't change until I change my URL

What i'm trying to do is basically keep the color of an link when I click on it, hovering the navbar link makes it greyish, and when I click on it and while it stays on the URL i want to keep it a different color.
I'm using react-router-dom for the Link component
<nav>
<ul className="nav-wrapper">
<li>
<Link className="link" to="/">
Home
</Link>
</li>
<li>
<Link className="link" to="/gallery">
Gallery
</Link>
</li>
<li>
<Link className="link" to="/about">
About
</Link>
</li>
</ul>
</nav>
I don't really know what to use here, i don't know if I should use a useState to try and change it when I click on it or change it on CSS, any tips are appreciated.
( I didn't understand your question well so I did both)
Ok! Try this to change an unvisited link (CSS)
a:link { color: what color you want; }
Use this to change a visited link (CSS)'
a:visited { color: what color you want; }
Code example:
a:active {
color: green;
}
a:visited {
color: purple;
}
<a href="#"> This link will change color<a>
Please mark an answer if you found one.
react-router-dom has an additional component called NavLink to which you can pass an additional prop called activeClassName. This will allow you to give custom styles to your active link.
example:
<NavLink to="/faq" activeClassName="selected">
FAQs
</NavLink>
This component will replace all of your Link components in your navigation.
use the :active psudo selector. docs
const [selectedItem, setSelectedItem] = useState(0);
<nav>
<ul className="nav-wrapper">
<li>
<Link className={`link ${selectedItem===0?'active':''}`} to="/" onClick={()=>setSelectItem(0)}>
Home
</Link>
</li>
<li>
<Link className={`link ${selectedItem===1?'active':''}`} to="/gallery" onClick={()=>setSelectItem(1)}>
Gallery
</Link>
</li>
<li>
<Link className={`link ${selectedItem===2?'active':''}`} to="/about" onClick={()=>setSelectItem(2)}>
About
</Link>
</li>
</ul>
</nav>
and then you can write on CSS,
li .active{
color: #your color;
}

How to loop through DOM and when a ID is clicked find corresponding class and toggle in React?

I'm new to React and coming from jQuery. I have the following code. I'm stuck on how to loop through my menu and when an element with id of #vans-by-manufacturer is clicked, then find an element with the same classname .vans-by-manufacturer and toggle a .open class on it?
const Nav = (props) => {
return (
<NavContainer className={props.open ? 'open' : ''}>
<button className='close-menu' onClick={props.close}>close</button>
<ul>
<li><Link href='/'>Offers</Link></li>
<li>
<Link href='/'>Vans ›</Link>
<div className='menu-secondary-container'>
<ul className='menu-secondary'>
<li className='title'>
<button type='button'>Vans</button>
</li>
<li className="home">
<Link href="/van-leasing.html">Vans Home</Link>
</li>
<li className='has-tertiary'>
<button type='button'
id='vans-by-manufacturer'>Vans By Manufacturer</button>
</li>
</ul>
<ul className='menu-tertiary vans-by-manufacturer'>
<li className='title'>
<button type='button'>‹ Vans By Manufacturer</button>
</li>
<li>
<Link href="/">Ford</Link>
</li>
<li>
<Link href="/">Vauxhall</Link>
</li>
</ul>
</div>
</li>
<li><Link href='/'>Pickups</Link></li>
<li><Link href='/'>Cars</Link></li>
</ul>
</NavContainer>
)} export default Nav
Thanks in advance
Look into useRef react hook.
On your element with '.vans-by-manufacturer' add a ref.
Add an onClick listener on the #vans-by-manufacturer and when it is clicked use the "ref" on the '.vans-by-manufacturer' to toggle the 'open' class.

Add class / remove class from li item in navbar (React)

I am trying to add 'active' class name to clicked navbar item dynamically and remove the 'active' class name from class respectively. I am using bootstrap so 'active' class name change the color of the li item.
class NavBar extends React.Component {
render() {
return (
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Blog - App</a>
</div>
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>Chat</li>
<li>About</li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
I am new with React, do i need to handle onClick with a function? I will appreciate any idea or code suggestions.
In react you can do it like this:
By passing in a prop which determines the toggle of className.
const NavBar = props => {
return (
<nav className="navbar navbar-inverse">
<div class="container-fluid">
<div className="navbar-header">
<Link className="navbar-brand">Blog - App</Link>
</div>
<ul className="nav navbar-nav">
<li className={props.active ? 'active' : ''}><Link to="/main">Home</Link></li>
<li><Link to="/chat">Chat</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</div>
</nav>
);
};
export default NavBar
By State
But then in this case wouldn't be appropriate because nothing is going to click it.
import {useState} from 'react';
const NavBar = () => {
const [active, setActive] = useState('');
clickToChange () {
setActive(true);
}
render() {
return (
<nav className="navbar navbar-inverse">
<div class="container-fluid">
<div className="navbar-header">
<Link className="navbar-brand">Blog - App</Link>
</div>
<ul className="nav navbar-nav">
<li className={state.active ? 'active' : ''}><Link to="/main">Home</Link></li>
<li><Link to="/chat">Chat</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
In your particular use case I'd probably suggest instead detecting the route
See example here:
React Router v4 - How to get current route?
yes, you could use onClick handler, but then again you will have to rehydrate it from the window.location;
class NavBar extends React.Component {
render() {
state = { active : null }
componentDidMount(){
/** you might as well check if location.pathname includes what you are looking
for before just setting it to state, assuming that there wont be anything
extra; skipping that for simplicity*/
this.setState(window.location.pathname);
}
handleClick = (activeLink) => {
this.setState(activeLink);
}
return (
<nav className="navbar navbar-inverse">
<div className="container-fluid">
<div className="navbar-header">
<a className="navbar-brand" href="#">Blog - App</a>
</div>
<ul className="nav navbar-nav">
<li onClick={()=>this.handleClick('/main')} className={`{this.state.active==='/main'? 'active':''}`}>Home</li>
</ul>
</div>
</nav>
);
};
};
export default NavBar
A more graceful implementation would be using a client side routing library like react-router which gives you Link components like NavLink which attaches active classnames automatically.

Categories