use React Hooks to change the elements class Name and siblings - javascript

I have this function component in react hooks.
and need when I click in any element in the list to change className to 'active'
and remove the className from the other elements
const SideBar = () =>{
const [activeClass, setClass] = useState('');
return (
<div className="sidebar">
<ul>
<li> <Link onClick={() => setClass('active')} className={activeClass} to="/"> Home </Link> </li>
<li> <Link to="/about"> About </Link> </li>
<li> <Link to="/form"> Form </Link> </li>
</ul>
</div>
)
}

I hope you must be using react-router-dom so you can use rect-router-dom api to determine the active item
import {
useLocation
} from "react-router-dom";
const SideBar = () =>{
const [activeClass, setClass] = useState('');
let { pathname } = useLocation();
return (
<div className="sidebar">
<ul>
<li> <Link className={pathname === '/' ? 'active' : ''} to="/"> Home </Link> </li>
<li> <Link to="/about" className={pathname === '/about' ? 'active' : ''}> About </Link> </li>
<li> <Link to="/form" className={pathname === '/form' ? 'active' : ''}> Form </Link> </li>
</ul>
</div>
)
}
import { NavLink } from 'react-router-dom';
const SideBar = () => {
const isActive = path => (match, location) => {
if (!match) {
return false;
}
return match.url === path;
};
return (
<div className="sidebar">
<ul>
<li> <NavLink isActive={isActive('/')} activeClassName="active" to="/"> Home </NavLink> </li>
<li> <NavLink to="/about" isActive={isActive('/about')} activeClassName="active"> About </NavLink> </li>
<li> <NavLink to="/form" isActive={isActive('/form')} activeClassName="active" > Form </NavLink> </li>
</ul>
</div>
)
}

So instead of maintaining only active/not active, you need to maintain which index in your links is active.
You can do this by this way:
const SideBar = () =>{
//setting the initial index as 0 to activate `/` route by default.
const [activeLinkIndex, setActiveLinkIndex] = useState(0);
return (
<div className="sidebar">
<ul>
<li> <Link onClick={() => setActiveLinkIndex(0)} className={activeLinkIndex === 0 ? 'active' : ''} to="/"> Home </Link> </li>
<li> <Link onClick={() => setActiveLinkIndex(1)} className={activeLinkIndex === 1 ? 'active' : ''} to="/about"> About </Link> </li>
<li> <Link onClick={() => setActiveLinkIndex(2)} className={activeLinkIndex === 2 ? 'active' : ''} to="/form"> Form </Link> </li>
</ul>
</div>
)
}

Related

NavLink Active property does not work with nested pages

I am using Reactjs in my project. NavLink active property does not work with nested pages inside the same tab?? It works just in the main tab anything inside the main tab does not work with. I want the white border appear in the main tab while open any pages inside it.
import { NavLink } from "react-router-dom";
function Navbar() {
let activeStyle = {
border: "solid 3px #FFF",
};
return (
<>
<nav className="navbar">
<ul className="nav-items">
{navItems.map((item) => {
if (item.id === "3") {
return (
<li
key={item.id}
className={item.cName}
onMouseClick={() => setDropdown(true)}
onMouseEnter={() => setDropdown(true)}
onMouseLeave={() => setDropdown(false)}
>
<NavLink to={item.title}
style={({ isActive }) =>
isActive ? activeStyle: undefined
}
>{item.title}</NavLink>
{dropdown && <Dropdown />}
</li>
);
}
return (
<li key={item.id}
className={item.cName}>
<NavLink to={item.path}
style={({ isActive }) =>
isActive ? activeStyle: undefined
}>{item.title}</NavLink>
</li>
);
})}
</ul>
</nav>
</>
);
}
export default Navbar;

How to optimize toggling className between different menu items by React?

I have header component, where I want to toggle className between all the elements of menu (if one of the elements of menu is active and user is clicking to another element - this element become active and all others no). I have a code like this
import React, { useState } from 'react';
import './header.scss';
export const Header = ({ favoriteCount }) => {
const [activeIndex, setActiveIndex] = useState(0);
function toggleClass(index) {
setActiveIndex(index);
}
return (
<header className="header">
<div className="container header-container">
<ul className="header-menu">
<li>
<a
className={
activeIndex === 0
? 'header-menu__link active'
: 'header-menu__link'
}
onClick={() => {
toggleClass(0);
}}
href="##"
>
Characters
</a>
</li>
<li>
<a
className={
activeIndex === 1
? 'header-menu__link active'
: 'header-menu__link'
}
onClick={() => {
toggleClass(0);
}}
href="##"
>
Favorites
</a>
</li>
</ul>
<div className="header-favorite-count">
<i className="far fa-heart"></i>
{favoriteCount}
</div>
</div>
</header>
);
};
and styles to visualise toggling classes
&-menu__link {
color: lightgray;
}
.active {
color: #fff;
}
This approach is working but looks creepy. Maybe somebody knows how to optimize it?
I wouldn't use the index, I'd use the text of the item. I'd also include that text in the href so that there's an indication of what the anchor leads to. To avoid repeated code, you might put the menu items in a reusable array, something like this:
const menuItems = [
"Characters",
"Favorites",
];
export const Header = ({ favoriteCount }) => {
const [activeItem, setActiveItem] = useState("");
const setActiveItem = useCallback((event) => {
setActiveItem(event.currentTarget.href.substring(2));
}, []);
const list = menuItems.map(item =>
<li key={item}>
<a
className={`header-menu__link ${item === activeItem ? "active" : ""}`}
onClick={setActiveItem}
href={"##" + item}>
{item}
</a>
</li>
);
return (
<header className="header">
<div className="container header-container">
<ul className="header-menu">
{list}}
</ul>
<div className="header-favorite-count">
<i className="far fa-heart"></i>
{favoriteCount}
</div>
</div>
</header>
);
};

Hide other previous div/dropdown React

I am wanting to hide other sibling divs (dropdowns in my case) when I click the statusPillDropdown
so far I click I am setting the status to true and opening the div,
{DropDown ${toggleStatusDropdown ? "open": ""}}
Do I just need to set the state to false for previously opened ones? Not sure how to do this.
thank you
import React, { useState } from "react";
import "./StatusPillDropdown.scss";
function StatusPillDropdown({
cellData,
rowItemId,
onStatusPillDropdownChange
}) {
const [toggleStatusDropdown, setToggleStatusDropdown] = useState();
const toggleDropdown = (action, rowItemId, e) => {
if (action === "pillClick") {
setToggleStatusDropdown(true);
} else {
onStatusPillDropdownChange(rowItemId, e.target.getAttribute("value"));
setToggleStatusDropdown(false);
}
};
const renderstatusPillDropdown = (cellData, rowItemId) => (
<React.Fragment>
<span
className="statusPillDropdown"
onClick={() => toggleDropdown("pillClick", rowItemId)}
>
<span className={`status-pill ${cellData.type}`}>{cellData.text}</span>
</span>
<div className="status">
<div className="dropdown-container">
<div className={`DropDown ${toggleStatusDropdown ? "open" : ""}`}>
<ul>
<li
value="Information only"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span></span>Information only
</li>
<li
value="Unresolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="unresolved"></span>Unresolved
</li>
<li
value="Partially Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="partyResolved"></span>Partially Resolved
</li>
<li
value="Fully Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="resolved"></span>Fully Resolved
</li>
</ul>
</div>
</div>
</div>
</React.Fragment>
);
return (
<React.Fragment>
{renderstatusPillDropdown(cellData, rowItemId)}
</React.Fragment>
);
}
export default StatusPillDropdown;

Reactjs Dropdown Menu not showing

I'm creating with reactjs Navbar which should include an dropdown menu component. I took the example from react bootstrap.
import React from 'react';
import {NavDropdown} from 'react-bootstrap'
export default function Dropdown() {
return (
<>
<div className="dropdown-style">
<NavDropdown title="Dropdown" id="collasible-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</div>
</>
)
}
But when I run this code the dropdown menu does not open in the front.
But the dev-mode shows me that it's actually opening.
The dropdown menu is only showing when I'm including this css-style
.dropdown-style{
position: absolute;
But when I shrink the window then this component tears up the whole navbar when I merge it to the burger menu
I tried
{ .z-index: 999 }
But this didn't work.
Here is the navigation component
export default class Navbar extends Component {
state = {
isOpen: false
};
handleToggle = () => {
this.setState({ isOpen: !this.state.isOpen });
};
render() {
return (
<nav className="navbar">
<div className="nac-center">
<div className="nav-header">
<Link to="/">
<img src={logo} alt="foo" id="foo" />
</Link>
<button
type="button"
className="nav-btn"
onClick={this.handleToggle}
>
<FaAlignRight className="nav-icon" />
</button>
</div>
<div className="ul-width nav-font">
<ul
className={this.state.isOpen ? "nav-links show-nav" : "nav-links nav-terms"}
>
<li className="navbar-top">
<Link to="/support"
onClick={(this.state.isOpen) ? this.handleToggle : null}>
Support
</Link>
</li>
<li className="navbar-top">
<Link to="/aboutus"
onClick={(this.state.isOpen) ? this.handleToggle : null}>
<nobr>About Us</nobr>
</Link>
</li>
<li className="navbar-top">
<Link to="/foo"
onClick={(this.state.isOpen) ? this.handleToggle : null}>
foo
</Link>
</li>
<li className="navbar-top">
<Dropdown/>
</li>
</ul>
</div>
</div>
</nav>
);
}
}
I've found out for myself now.
If one of you have the same problem, just overwrite the css-class with .dropdown-menu { position:relative !important }
it seems that dropdown-menu is written by react itself and you just have to overwrite it.

Converting JavaScript to work with React component

New to React and am trying to write my script in React but not sure how to do it.I've tried using states but that has just clouded me with more confusion. The below code is a sample of something I might commonly create.
Here's my script:
const hamburger = document.querySelector(".hamburger");
hamburger.addEventListener("click", function () {
hamburger.classList.toggle("is-active");
document.querySelector(".navigation").classList.toggle("slide-in");
document.querySelector("body").classList.toggle("menu-active");
document.querySelector(".shell-ui-main").classList.toggle("menu-overlay");
});
Here's a basic react component for a navbar:
import React from 'react';
export default class NavComponent extends React.Component {
render() {
return (
<div className="container">
<button className="hamburger hamburger--squeeze" type="button">
<span className="hamburger-box">
<span className="hamburger-inner"></span>
</span>
</button>
<a className="logo-link" href="/">
<img width="94" height="31" src="/img/logos/logo.png" srcSet="/img/logos/logo.png 1x, /img/logos/logo#2x.png 2x, /img/logos/logo#3x.png 3x"
alt="logo" className="logo" />
</a>
<nav className="navigation">
<ul className="nav">
<li className="single-item">
Home
</li>
<li className="single-item">
Item 2
</li>
<li className="single-item">
Item 3
</li>
<li className="single-item">
Item 4
</li>
</ul>
</nav>
</div>
);
}
}
Here's the solution in case anyone is interested. Additionally I pass the props down to the component and control from there instead of the individual const.
import React from 'react';
const HamburgerToggle = (props) => (
<button className={"hamburger hamburger--squeeze" + (props.active ? " is-active" : "")} onClick={props.clickHandler} type="button">
<span className="hamburger-box">
<span className="hamburger-inner"></span>
</span>
</button>
);
const Logo = () => (
<a className="logo-link" href="/">
<img width="94" height="31" src="/img/logos/logo.png" srcSet="/img/logos/logo.png 1x, /img/logos/logo#2x.png 2x, /img/logos/logo#3x.png 3x" alt="Logo" className="logo" />
</a>
);
const Navigation = (props) => (
<nav className={"navigation" + (props.active ? " slide-in" : "")}>
<ul className="nav">
<li className="single-item">
Home
</li>
<li className="single-item">
intem 2
</li>
<li className="single-item">
item 3
</li>
<li className="single-item">
item 4
</li>
</ul>
</nav>
);
export default class NavComponent extends React.Component {
state = {active: false};
handleClick(e){
this.setState({active: !this.state.active});
console.log(this.state.active);
}
render() {
return (
<div className="container">
<HamburgerToggle active={this.state.active} clickHandler={this.handleClick.bind(this)} />
<Logo />
<Navigation active={this.state.active} clickHandler={this.handleClick.bind(this)} />
</div>
);
}
}

Categories

Resources