React Router get which `<NavLink />` is active? - reactjs

I render some <NavLink /> like below
<div class="container">
<NavLink to="/" exact></NavLink>
<NavLink to="/profile"></NavLink>
<NavLink to="/message"></NavLink>
</div>
it's cool that react-router will add an active class to which is currently matched.
but how do I know which one is currently active ?
because I have some other styles to adjust based on this, like when in '/' I want to give .container 100px padding-left, and when in '/profile', I want to give .container 200px padding-left.

You can use withRouter to get the path of the current page, by using pathname you can file which is your current page.
import React from "react";
import { withRouter } from "react-router";
class Location extends React.Component {
render() {
const { match, location, history } = this.props;
return <div>You are now at {location.pathname}</div>;
}
}
const WithRouter = withRouter(ShowTheLocation);

You can add a different activeClassName to each of them.
(See https://reacttraining.com/react-router/web/api/NavLink)
For example
<div class="container">
<NavLink to="/" exact></NavLink>
<NavLink to="/profile" activeClassName="matched-profile"></NavLink>
<NavLink to="/message"></NavLink>
</div>
Then style container like this .container:has(.matched-profile)

Related

How to change Icon on Navlink when active?

I'm making a tab bar for phone in react js and i have icons on it. I'm using React Router to perform the routes. Right now im able to change the icon color when it is active using an .active class. Is there a way I can change the Icon File when the route is active? Here is the code attached below.
import React, { Component } from 'react';
import {NavLink} from 'react-router-dom';
import home_icon_stroke from './home_icon_stroke.svg';
import explore_icon_stroke from './explore_icon_stroke.svg';
import activity_icon_stroke from './activity_icon_stroke.svg';
import library_icon_stroke from './library_icon_stroke.svg';
import profile_icon_stroke from './profile_icon_stroke.svg';
import './Phonetabbar.css';
export default class Phonetabbar extends Component {
render() {
return (
<div className="phone-tabbar-layout" >
<div className="fixed" >
<div className="phone-tabbar-list">
<div className="tabbar-cell">
<NavLink exact to="/" >
<img src={home_icon_stroke} ></img>
</NavLink>
</div>
<div className="tabbar-cell">
<NavLink to="/explore" >
<img src={activity_icon_stroke} ></img>
</NavLink>
</div>
</div>
</div>
</div>
)
}
}
Maybe you want to try passing the isActive function to Navlink, setting a state in it.
<NavLink exact to="/"
isActive={(match, location)=>{
if(match){
//set isActive state true
}
return match;
}
>
<img src={isActive?home_icon_stroke:anotherImg} ></img>
</NavLink>

NavLink active on same link for multiple URLs in React Router DOM

I have a page with multiple tabs (child). I also change the URL for each tab, but I'm still on the parent page, just changing the URL for the tab.
the problem is that I can't keep the parent page NavLink active when I click on the tab 'cause it changes the URL, but I want to keep that Active on the Tabs URL.
How to do this?
import React from 'react';
import { NavLink } from 'react-router-dom';
export default () => {
return (
<>
<nav className='Navigation'>
<ul className={`Navigation__list ${hide}`}>
<li className='Navigation__list-item'>
<NavLink to="/events" >Events</NavLink>
</li>
</ul>
</nav>
<Tabs />
</>
);
}
// Tabs Component As Child
export default function Tabs () => (
<ul className="events__tab">
<li> <NavLink to="/events"> All Events </NavLink> </li>
<li> <NavLink to="/myevents"> My Events </NavLink> </li>
</ul>
)
Thanks for your Support in Advance!
All you have to do is to Write a condition inside isActive in NavLink, if the current page URL matches with defined URLs, return true otherwise false. use the function inside isActive, if it return true, you'll get active Link..
Example:
isActive={ () => ['/example', '/exampl2'].inclues(currentPageUrl) }
if the current URL matches in the Above Array, your NavLink will be Active as long as URL doesn't match.
for finding the Current Page URL use the useLocation() hook.
import React from 'react';
import { useLocation } from 'react-router-dom';
// Active the Link on two URLs
export default () => {
// extract pathname from location
const { pathname } = useLocation();
return (
<li className='Navigation__list-item'>
<NavLink
to="/events"
isActive={() => ['/events', '/myevents'].includes(pathname)} >
Events
</NavLink>
</li>
);
};

React-Router: pass props from one component to another using Navlink

I am using <NavLink> for routing now how can i pass props into <NavLink> to another Component
The way you can pass data to navigated component using Link and NavLink
<Link to={{
pathname:'/home',
state: {name:'from home page'}
}}>
Go to Home
</Link>
or using NavLink
<NavLink to={{
pathname:'/home',
state: {title:'from home page'}
}}>
Go to Home
</NavLink>
inside navigated component you can access like this.
if it's hooks
import {useLocation} from 'react-router-dom'
function App(){
let location = useLocation();
console.log(location)
return <h2>...</h2>
}
if it's class based component
console.log(this.props.location)
On the first component do this
<NavLink
to={{
pathname:"/priview-data",
aboutProps:{
selectedidds:this.state.selectedIds
}
}}
exact
>Preview Question
</NavLink>
and now on another component
constructor(props) {
super(props);
console.log(props.location.aboutProps);
}
hope it helps
Thanks
You can also use hooks to pass props:
<Link
to={{
pathname: "/home",
userProps: {name: "This is a passed prop"},
}}>
Go to home
</Link>
To access it from another component
import { useLocation} from "react-router-dom"
function OtherComponent() {
let location = useLocation();
console.log(location.userProps);
}
<NavLink to="/onboarding/profile" state={{ from: "occupation" }}>
Next Step
</NavLink>
Now the only question that remains is, how do we get access to the data on state so we can update the UI based on it? To answer that, we need to look at the component that's being rendered at the /onboarding/profile route. For our example, let's call it Profile.
import { useLocation } from 'react-router-dom'
function Profile () {
let location = useLocation();
console.log(location.state.from);
return (
...
)
}

"React does not recognize the prop on a DOM element" in React Router

React does not recognize the computedMatch prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase computedmatch instead. If you accidentally passed it from a parent component, remove it from the DOM element.
This is the code in question:
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
NavLink
} from "react-router-dom";
import "./AdminPage.css";
export default class AdminPage extends React.Component {
render() {
return (
<div>
<Router>
<nav>
<ul className="nav nav-tabs">
<li className="nav-item">
<NavLink to="/admin/books" className="nav-link" activeClassName="active">Books</NavLink>
</li>
<li className="nav-item">
<NavLink to="/admin/branches" className="nav-link" activeClassName="active">Branches</NavLink>
</li>
<li className="nav-item">
<NavLink to="/admin/members" className="nav-link" activeClassName="active">Members</NavLink>
</li>
</ul>
</nav>
<Switch>
<div> <!-- this appears to be the element that is receiving a "computedMatch" property -->
<Route exact path="/admin/books">
Books
</Route>
</div>
</Switch>
</Router>
</div>
)
}
}
because Switch passes computedMatch to the first child that meets one of 2 conditions:
has either a path or a form prop that matches the current location.
has none of these 2 props (path, form)
The element in question in your code is that div.
Inside the render method of Switch.js, you will see this:
React.Children.forEach(this.props.children, child => {
if (match == null && React.isValidElement(child)) {
element = child;
const path = child.props.path || child.props.from;
match = path
? matchPath(location.pathname, { ...child.props, path })
: context.match;
}
});
return match
? React.cloneElement(element, { location, computedMatch: match })
: null;
And since computedMatch isn't a legal DOM attribute/property, you get the warning.
Unknown Prop Warning
Only when running the Jest test would I encounter this warning.
render(<Popup><div>test</div></Popup>);
The Poupup React component uses React.cloneElement in its implementation to pass props down into the rendered child.
In the test since I was passing a regular HTML element the props contained unrecognised HTML properties.
The fix was to render the test with a proper React element instead:
const TestElement = () => <div>test</div>
render(<Popup><TestElement /></Popup>);

Trying to use Bootstrap Nav Pills in React Router's NavLink

I am having trouble using the default Bootstrap Nav pills as the links on the Navbar for my page, where they show if the pill is active or not. As I have the code, the NavLink is just in plain text and I can't seem to use any of the active styling from Bootstrap.
I am using Bootstrap 4 and React with React Router.
import React, { Component } from "react";
import { NavLink } from "react-router-dom";
class NavBar extends Component {
render() {
return (
<nav className="navbar navbar-expand-lg bg-light navbar-light">
<ul className="nav nav-pills">{this.renderNavLinks()}</ul>
</nav>
);
}
renderNavLinks() {
const navButton = {
padding: "10px"
};
return this.props.navLinks.map(l => (
<li className="nav-item" style={navButton}>
<NavLink className="active" to={"/" + l.id}>{l.text}</NavLink>
</li>
));
}
}
export default NavBar;
I want my NavBar to actively show what page is currently being displayed using Bootstrap's default pill style buttons.
You are missing the nav-link css class on the NavLink component.
<NavLink className="nav-link" to={"/" + l.id}>{l.text}</NavLink>
Reference

Resources