可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am new to the ReactJS world, and would like to know how can I pass active class name to the <li>
element instead of <a>(Link)
element.
Now I have this kind of code. The anchor class changes when clicked.
<li><IndexLink to='/' activeclassName='active'>A</IndexLink></li>
<li><Link to='/b' activeclassName='active'>B</Link></li>
<li><Link to='/c' activeclassName='active'>C</Link></li>
But I would like to get something similar to:
<li activeclassName='active'><IndexLink to='/'>A</IndexLink></li>
<li activeclassName='active'><Link to='/b'>B</Link></li>
<li activeclassName='active'><Link to='/c'>C</Link></li>
Thanks in advance
回答1:
You need to enclose your <li>
as a router aware component:
import { Link, IndexLink } from 'react-router'
class NavItem extends React.Component {
render () {
const { router } = this.context
const { index, onlyActiveOnIndex, to, children, ...props } = this.props
const isActive = router.isActive(to, onlyActiveOnIndex)
const LinkComponent = index ? Link : IndexLink
return (
<li className={isActive ? 'active' : ''}>
<LinkComponent {...props}>{children}</LinkComponent>
</li>
)
}
}
Usage:
<ul>
<NavItem to='/' index={true}>Home</NavItem>
<NavItem to='/a'>A</NavItem>
</ul>
I took inspration from the react-router-bootstrap module, https://github.com/react-bootstrap/react-router-bootstrap/blob/master/src/LinkContainer.js. I didn't test it though so let me know how it goes.
回答2:
The other answers don't seem to work in React Router v4. Here's how you can do it:
import React, {PropTypes} from 'react'
import {Route, Link} from 'react-router-dom'
import styles from './styles.less';
export default function NavItem({children, to, exact}) {
return (
<Route path={to} exact={exact} children={({match}) => (
<li className={match ? styles.activeRoute : null}>
<Link to={to}>{children}</Link>
</li>
)}/>
)
}
NavItem.propTypes = {
to: PropTypes.string.isRequired,
exact: PropTypes.bool,
children: PropTypes.node.isRequired,
};
回答3:
/**
* A navigation component
*/
import React, { Component } from 'react'
import { Link, IndexLink, withRouter } from 'react-router'
import styles from './styles.scss'
class NavItem extends Component {
render () {
const { router } = this.props
const { index, to, children, ...props } = this.props
let isActive
if( router.isActive('/',true) && index ) isActive = true
else isActive = router.isActive(to)
const LinkComponent = index ? IndexLink : Link
return (
<li className={isActive ? 'active' : ''}>
<LinkComponent to={to} {...props}>{children}</LinkComponent>
</li>
)
}
}
NavItem = withRouter(NavItem)
export default NavItem
Usage:
<ul className="nav nav-tabs">
<NavItem to='/home' index={true} >Home</NavItem>
<NavItem to='/about'>About</NavItem>
</ul>
回答4:
In stead of using <Link />
, I use <NavLink />
and It works as well.
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
//.....
export default class AppNav extends Component {
render (){
return (
<header>
<ul className="main-nav">
<li><NavLink activeClassName={"active"} exact={true} to="/">Home</NavLink></li>
<li><NavLink activeClassName={"active"} to="/about">About</NavLink></li>
<li><NavLink activeClassName={"active"} to="/courses">Courses</NavLink></li>
</ul>
</header>
);
}
}
回答5:
{/* Make sure that `location` is injected into this component */}
<ul className="nav navbar-nav">
<li className={location.pathname === '/' && 'active'}>
<Link to='/'>
Home page
</Link>
</li>
<li className={location.pathname.startsWith('/about') && 'active'}>
<Link to='/about'>
About us
</Link>
</li>
</ul>
回答6:
Great answer.
Just change the following to get it working...
LinkComponent = index ? IndexLink : Link //If its true you want an IndexLink
//Also link needs to be...
<NavItem to="/" onlyActiveOnIndex index={true}>Home</NavItem>
回答7:
Try with react-router-active-component.
I couldn't get any of the previous answers to easily work due to incompatibilities between react or typescript versions (this is definitely not a mature ecosystem), but this component did the trick, and can be applied to other elements than li
if needed:
import activeComponent from 'react-router-active-component'
let NavItem = activeComponent('li');
...
<NavItem to='/' onlyActiveOnIndex>Home</NavItem>
<NavItem to='/generate-keywords'>Generate keywords</NavItem>
回答8:
Using react 15.1.0, react-router 2.5.0 and bootstrap 3.3 (this is less important), I developed this solution for making the links active:
npm install --save classnames
npm install --save lodash
The component:
import React from 'react';
import { Link, IndexLink } from 'react-router';
import _ from 'lodash';
import classnames from 'classnames';
class NavItem extends React.Component {
constructor(props) {
super(props);
// The default state
this.state = {
isActive: false,
unregisterRouteListener: false
};
// Binding for functions
this.locationHasChanged = this.locationHasChanged.bind(this);
}
componentDidMount() {
// Check if component is active on mount and add listener on route change
this.setState({
isActive: this.context.router.isActive(this.props.to, true),
unregisterRouteListener: this.context.router.listen(this.locationHasChanged)
});
}
componentWillUnmount() {
if (this.state.unregisterRouteListener) {
// Remove the listener
this.state.unregisterRouteListener();
}
// Reset the state
this.setState({
isActive: false,
unregisterRouteListener: false
});
}
// Update the state of the component, based on the router path
locationHasChanged() {
this.setState({
isActive: this.context.router.isActive(this.props.to, true)
});
}
render () {
let { index } = this.props;
let LinkComponent = index ? Link : IndexLink;
let newProps = _.omit(this.props, 'router');
return (
<li className={classnames('', this.state.isActive ? 'active' : '' )}>
<LinkComponent {...newProps}>
{this.props.children}
</LinkComponent>
</li>
);
}
}
NavItem.contextTypes = {
router: React.PropTypes.object
};
export default NavItem;
Usage:
<NavItem to="/list">List</NavItem>
I am a beginner with React, so the above solution surely needs improvements and might contain approach errors. However, it might also contain useful information or a starting point to those interested.
Any feedback or suggestions are more than welcome. Thanks! :)
回答9:
Using React Router v4, I only got it to work by including the <li>
tags within the NavLink component. The solutions which have the <li>
tags wrapping the links resulted in the HOME <li>
tag always having the active
class.
import React from 'react'
import { NavLink } from 'react-router-dom';
class Header extends React.Component {
render() {
return (
<div>
<header>
<nav>
<ul>
<NavLink activeClassName={"active"} exact={true} to="/"><li>Home</li></NavLink>
<NavLink activeClassName={"active"} to="/about"><li>About</li></NavLink>
<NavLink activeClassName={"active"} to="/courses"><li>Courses</li></NavLink>
</ul>
</nav>
</header>
</div>
)
}
}
export default Header
I adjusted the li
and a
CSS selectors accordingly.
回答10:
I'm using React Router v4.2 and I couldn't get the reference to the router object from the wrapping component, because the context is not available.
This did not work:
const { router } = this.context
I like @mpen's answer, but I'm using nested routes and I don't want to change the file where I have the routing component defined.
What I did is compared the location.pathname with to :
const NavItem = withRouter((props) => {
const { to, children, location } = props;
return (
<li className={location.pathname == to ? 'active' : null}>
<Link to={to}>{children}</Link >
</li>
)});