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.
Related
I am trying to make the actively selected navbar element change the background color via react state. However it does not fully work. When I click on an element in my navbar, it briefly gets styled correctly, but after a moment is reverted and my homepage element in the navbar becomes styled once more.
I have my (simplified) navbar code below:
function Navbar(props) {
const [clickedNavbarItem, setClickedNavbarItem] = React.useState("/");
return (
<ul>
<li>
<a
onClick={() => setClickedNavbarItem("/")}
className={clickedNavbarItem === "/" && "active"}
href="/"
>Solve
</a>
</li>
<li>
<a
onClick={() => setClickedNavbarItem("/about")}
className={clickedNavbarItem === "/about" && "active"}
href="/about"
>About
</a>
</li>
</ul>
)
}
To my understanding: When the user clicks a given anchor tag, it should run the onClick handler, which will re-assign the state. The navbar should then re-render, and the classname for the appropriately clicked item should have the "active" class, which should change the styling.
Additionally, the href should redirect the page as such (this is my React router code):
function App() {
return (
<>
<Navbar />
<Routes>
<Route path="/" element={<Solve />} />
<Route path="/about" element={<About />} />
<Route path="/explain" element={<Explain />} />
</Routes>
</>
)
}
I believe there is some interaction where the Navbar is getting reset perhaps when the href is activated, but I'm not entirely sure. Any help is appreciated.
<Route path='/dashboard' element={<Navbar />}>
<Route index element={<Home />} />
<Route path='profile' element={<Profile />} />
<Route path='wallets' element={<Wallet />} />
<Route path='users' element={<Users />} />
</Route>
Here's my code and what basically happens is in my Navbar I got the active page link marked blue
So when I'm on /dashboard it shows Home in blue
But when I'm on /dashboard/profile it shows both home and profile in blue
<li>
<NavLink to=''>
{({ isActive }) =>
isActive ? (
<text style={{color: blue}}>Home</text>
) : (
<text>Home</text>
)
}
</NavLink>
</li>
<li>
<NavLink to='profile'>
{({ isActive }) =>
isActive ? (
<text style={{color: blue}}>Profile</text>
) : (
<text>Profile</text>
)
}
</NavLink>
</li>
You can specify the end prop on the "root"-level link to the "/dashboard" path.
NavLink
If the end prop is used, it will ensure this component isn't matched
as "active" when its descendant paths are matched.
<NavLink to='' end>
{({ isActive }) =>
isActive ? (
<text style={{color: blue}}>Home</text>
) : (
<text>Home</text>
)
}
</NavLink>
<NavLink to="/">Home</NavLink>
<NavLink to="/profile">Profile</NavLink>
<NavLink to="/wallets">Wallet</NavLink>
Here React Router considers the /path the same as the /about. By including the end prop, the active class will be applied only when the URL matches its attributes.
NavLink to="/profile" style={({isActive}) => isActive ? {background: "hotpink"} : undefined} >Profile</NavLink>
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 am a new in React world in want to now why this code is always render every time i made a change on the page it always render the components that is no change made, for example:
<Grid columns="equal" className="app" style={{ background: secondaryColor.hex }}>
<ColorPanel
key={currentUser && currentUser.name}
currentUser={currentUser}
/>
<SidePanel
key={currentUser && currentUser.uid}
currentUser={currentUser}
primaryColor={primaryColor}
/>
<Grid.Column style={{ marginLeft: 320 }}>
<Messages
key={currentChannel && currentChannel.id}
currentChannel={currentChannel}
currentUser={currentUser}
isPrivateChannel={isPrivateChannel}
/>
</Grid.Column>
<Grid.Column width={4}>
<MetaPanel
key={currentChannel && currentChannel.name}
userPost={userPost}
currentChannel={currentChannel}
isPrivateChannel={isPrivateChannel}
/>
</Grid.Column>
</Grid>
I made a change on the MessagePanel component and the entiry app render again.
Hi can you test with the React Pure component class and React.memo functions, those functions help you to prevent re-render on the React components for example: If you have a class component you extends from PureComponent besides Components Pure component class do a shallow validation on the props of the component if a change is between the props the component is render againg, the same behavior is with the React.memo the only thing is the last one if for functional component here are the links of the React documentation:
React.memo example:
const NavMemo = React.memo(({ activeTab, onTabChange }) => {
console.log('Render');
return (
<nav className="App-nav">
<ul>
<li className={`App-nav-item ${activeTab === 0 && 'selected'}`}>
<a onClick={() => onTabChange(0)}>Items</a>
</li>
<li className={`App-nav-item ${activeTab === 1 && 'selected'}`}>
<a onClick={() => onTabChange(1)}>Cart</a>
</li>
</ul>
</nav>
);
});
React Pure Component Example:
export default class Nav extends React.PureComponent {
render() {
const { onTabChange, activeTab } = this.props;
return (
<nav className="App-nav">
<ul>
<li className={`App-nav-item ${activeTab === 0 && 'selected'}`}>
<a onClick={() => onTabChange(0)}>Items</a>
</li>
<li className={`App-nav-item ${activeTab === 1 && 'selected'}`}>
<a onClick={() => onTabChange(1)}>Cart</a>
</li>
</ul>
</nav>
);
}
}
https://reactjs.org/docs/react-api.html#reactmemo
https://reactjs.org/docs/react-api.html#reactpurecomponent