How to set activeClassName for wrapper element of Link or IndexLink in react-router?

前端 未结 10 1488
醉酒成梦
醉酒成梦 2020-12-07 15:56

I am new to the ReactJS world, and would like to know how can I pass active class name to the

  • element instead of (Link) element
  • 相关标签:
    10条回答
    • 2020-12-07 16:14

      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,
      };
      
      0 讨论(0)
    • 2020-12-07 16:16

      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>
        );
      });
      
      0 讨论(0)
    • 2020-12-07 16:21
      {/* 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>
      
      0 讨论(0)
    • 2020-12-07 16:22

      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>
              );
          }
      }
      
      0 讨论(0)
    • 2020-12-07 16:23

      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.

      0 讨论(0)
    • 2020-12-07 16:23

      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! :)

      0 讨论(0)
    提交回复
    热议问题