I am trying to add an active class to the nav link of the page you are on, however, no matter which page you are on, the homepage always has the active class. As you can see here, both home and about are green when on the about page - https://gyazo.com/8ad3f7c455075bad53344372d56b9b4a
My code is below. When I checked this in the console with logs, it seems the home navlink is always in an active state, why is this? https://gyazo.com/40faf1ee4a076d78edff7596daa44845
In past react apps, I just used the activeClassName and it worked fine
import React from "react";
import { NavLink } from "react-router-dom";
import "./../App.css";
function Navbar() {
return (
<nav>
<NavLink
to="/"
className={({ isActive }) => "nav-link" + (isActive ? " active" : "")}
>
<span className="nav-text">Home</span>
</NavLink>
<NavLink
to="/about"
className={({ isActive }) => "nav-link" + (isActive ? " active" : "")}
>
<span className="nav-text">About</span>
</NavLink>
<NavLink
to="/services"
className={({ isActive }) => "nav-link" + (isActive ? " active" : "")}
>
<span className="nav-text">Services</span>
</NavLink>
<NavLink
to="/contact"
className={({ isActive }) => "nav-link" + (isActive ? " active" : "")}
>
<span className="nav-text">Contact</span>
</NavLink>
</nav>
);
}
export default Navbar;
Related
I called a function inside the style attribute.
I want to change a state value based on which NavLink is active,
So I made the callback function inside the style attribute because the style callback function has a default parameter that checks if the NavLink is active or not.
<NavLink
to="/"
style={({ isActive }) => {
if (isActive) {
setActive("Home");
}
}}
>
<span className={`icon `}>
{active === "Home" ? <HouseDoorFill /> : <HouseDoor />}
</span>
<span className="title">Home</span>
</NavLink>
That is the warning I get.
Warning
Location
I want to know if this warning is critical or not, and how can I solve this issue.
It's that fact that you are enqueueing a state update as an unintentional side-effect during the render cycle. The style prop should be returning a React.CSSProperties style object though when used. You don't need any state here though as you can use a children render function that receives the isActive prop.
Example:
<NavLink to="/">
{({ isActive }) => (
<>
<span className="icon">
{isActive ? <HouseDoorFill /> : <HouseDoor />}
</span>
<span className="title">Home</span>
</>
)}
</NavLink>
If you must keep the active state then use an onClick handler to issue the effect of updating the React state.
<NavLink
to="/"
onClick={() => setActive("Home")}
>
<span className="icon">
{active === "Home" ? <HouseDoorFill /> : <HouseDoor />}
</span>
<span className="title">Home</span>
</NavLink>
See the NavLink documentation for more detail.
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;
Exactly what I want is isActive which is in the NavLink function in the React Router Dom. However, I want to render SVG conditionally. Do you have any other solution? Thank you.
<NavLink
to="/"
style={({ isActive }) => (isActive ? activeStyle : undefined)}
>
Home
<NavLine className="active-line" />
</NavLink>
<NavLink
to="/asd"
style={({ isActive }) => (isActive ? activeStyle : undefined)}
>
Work
<NavLine className="active-line" />
</NavLink>
<NavLink
to="/dsa"
style={({ isActive }) => (isActive ? activeStyle : undefined)}
>
About
<NavLine className="active-line" />
</NavLink>
</div>```
I have a dropdown list that contains account names and accounts Ids. The dropdown is a child that lives in my NavMenu.js titled AccountsDropdown
render () {
return (
<header>
<Navbar className="navbar-expand-sm navbar-toggleable-sm ng-white border-bottom box-shadow mb-3" light>
<Container>
<div><NavbarBrand className="brand-name" tag={Link} to="/">PABST</NavbarBrand><br />
<NavbarText className="sub-headline" to="/">Budget Allocation & Forecasting</NavbarText></div>
<NavbarToggler onClick={this.toggleNavbar} className="mr-2" />
<AccountsDropdown></AccountsDropdown>
<Collapse className="d-sm-inline-flex flex-sm-row-reverse center-align-flex margin-right" isOpen={!this.state.collapsed} navbar>
<ul className="navbar-nav flex-grow">
<NavItem>
<NavLink tag={Link} id={"budgetplanner"} onClick={() => this.handleChange("budgetplanner")} className={"budgetplanner" === this.state.selectedNavItem ? "active" : "inactive"} to="/"><EventNoteIcon ></EventNoteIcon>Budget Planner</NavLink>
</NavItem>
<NavItem>
<NavLink tag={Link} id={"budgetresults"} onClick={() => this.handleChange("budgetresults")} className={"budgetresults" === this.state.selectedNavItem ? "active" : "inactive"} to="/budget-results"><PieChartRoundedIcon></PieChartRoundedIcon>Budget Results</NavLink>
</NavItem>
<NavItem>
<NavLink tag={Link} id={"docs"} onClick={() => this.handleChange("docs")} className={"docs" === this.state.selectedNavItem ? "active" : "inactive"} to="/fetch-data"><FolderRoundedIcon></FolderRoundedIcon>Docs</NavLink>
</NavItem>
</ul>
</Collapse>
This menu as you can see also has redirects to my other JSX pages. So for example, when a user clicks on Budget Results, they get redirected to the Budget Results page. This Budget Results page is a top level parent. It is not a child of any other component. Here is the code:
import React, { Component } from 'react';
import MainGridComponent from './MainGridComponent';
import '../css/main.css';
export class BudgetResults extends Component {
static displayName = BudgetResults.name;
constructor(props) {
super(props);
this.state = {
accountid: "1"
};
}
render() {
return(
<div className="row">
<div className="col-md-8 budget-results">
<span className="grid-header">Recent Budget Output</span>
<MainGridComponent accountid={this.state.accountid} pagetype="BudgetResults"></MainGridComponent>
</div>
</div>
);
}
}
export default BudgetResults
As you can see, AccountsDropdown and BudgetResults are entirely unrelated. My question is, is it possible to cause a rerender on BudgetResults when AccountsDropdown changes its state? Is this something that's only possible with Redux?
Redux is not compulsory to achieve this.
Add a common ancestor to BudgetResults & AccountsDropdown.
Move the state up to this ancestor.
Then you can use either prop callbacks or the Context API to achieve it.
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>
)
}