javascript-如何在react-router中为Link或IndexLink的包装元素设置activeClassName?

我是ReactJS世界的新手,并且想知道如何将活动的类名传递给<li>元素而不是<a>(Link)元素。

现在,我有这种代码。 单击时,锚类会更改。

<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>

但我想得到类似的东西:

<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>

提前致谢

abekenza asked 2020-06-26T23:41:25Z
10个解决方案
37 votes

您需要将<li>封装为路由器感知组件:

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>
    )
  }
}

用法:

<ul>
  <NavItem to='/' index={true}>Home</NavItem>
  <NavItem to='/a'>A</NavItem>
</ul>

我从react-router-bootstrap模块[https://github.com/react-bootstrap/react-router-bootstrap/blob/master/src/LinkContainer.js。]中进行了检查。 让我知道事情的后续。

Marc Greenstock answered 2020-06-26T23:41:43Z
18 votes

其他答案似乎在React Router v4中不起作用。 方法如下:

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,
};
mpen answered 2020-06-26T23:42:03Z
10 votes
/**
 * 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

用法:

<ul className="nav nav-tabs"> 
  <NavItem to='/home' index={true} >Home</NavItem>
  <NavItem to='/about'>About</NavItem>
</ul>
bryanyu answered 2020-06-26T23:42:23Z
5 votes
{/* 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>
kenberkeley answered 2020-06-26T23:42:38Z
5 votes

代替使用<Link />,我使用<NavLink />,它也能正常工作。

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>
        );
    }
}
Dimang Chou answered 2020-06-26T23:42:58Z
3 votes

好答案。

只需更改以下内容即可使其正常工作...

LinkComponent = index ? IndexLink : Link //If its true you want an IndexLink 

//Also link needs to be...
<NavItem to="/" onlyActiveOnIndex index={true}>Home</NavItem>
Matthew Berends answered 2020-06-26T23:43:22Z
1 votes

尝试使用react-router-active-component。

由于react或打字稿版本之间不兼容(这绝对不是一个成熟的生态系统),我无法轻松获得之前的任何答案,但是此组件确实可以解决问题,并且可以根据需要将其应用于除li之外的其他元素:

import activeComponent from 'react-router-active-component'
let NavItem = activeComponent('li');
...
<NavItem to='/' onlyActiveOnIndex>Home</NavItem>
<NavItem to='/generate-keywords'>Generate keywords</NavItem>
Erwin Mayer answered 2020-06-26T23:43:47Z
1 votes

使用react 15.1.0,react-router 2.5.0和bootstrap 3.3(这不太重要),我开发了此解决方案以使链接处于活动状态:

npm install --save lodash

npm install --save lodash

组件:

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;

用法:

<NavItem to="/list">List</NavItem>

我是React的初学者,因此上述解决方案当然需要改进,并且可能包含方法错误。 但是,它也可能包含有用的信息或对感兴趣者的起点。

任何反馈或建议都非常欢迎。 谢谢! :)

Cristi Draghici answered 2020-06-26T23:45:29Z
1 votes

我正在使用React Router v4.2,但由于上下文不可用,所以无法从包装组件中获得对路由器对象的引用。

这不起作用:

const { router } = this.context

我喜欢@mpen的答案,但是我使用的是嵌套路由,我不想更改定义了路由组件的文件。

我所做的是将location.pathname与进行了比较:

const NavItem = withRouter(props => {
  const { to, children, location } = props;
  return (
    <li className={location.pathname == to ? "active" : null}>
      <Link to={to}>{children}</Link>
    </li>
  );
});
Jernej Gorički answered 2020-06-26T23:46:02Z
0 votes

使用React Router v4,我只能通过将li标签包含在NavLink组件中来使其工作。 具有a标签包裹链接的解决方案导致HOME <li>标签始终具有active类。

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

我相应地调整了lia CSS选择器。

Steve Breese answered 2020-06-26T23:46:27Z
translate from https://stackoverflow.com:/questions/35053161/how-to-set-activeclassname-for-wrapper-element-of-link-or-indexlink-in-react-rou