wake-up-neo.com

Wie setze ich activeClassName für das Wrapper-Element von Link oder IndexLink im React-Router

Ich bin neu in der ReactJS-Welt und möchte wissen, wie ich einen aktiven Klassennamen an das <li>-Element anstelle des <a>(Link)-Elements übergeben kann.

Jetzt habe ich diese Art von Code. Die Ankerklasse ändert sich, wenn Sie darauf klicken.

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

Aber ich würde gerne etwas Ähnliches bekommen:

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

Danke im Voraus

42
abekenza

Sie müssen Ihren <li> als Komponente für den Router angeben:

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

Verwendungszweck:

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

Ich habe die Inspration vom Reakt-Router-Bootstrap-Modul https://github.com/react-bootstrap/react-router-bootstrap/blob/master/src/LinkContainer.js übernommen. Ich habe es jedoch nicht getestet, also lassen Sie mich wissen, wie es läuft.

37
Marc Greenstock

Die anderen Antworten scheinen in React Router v4 nicht zu funktionieren. So kannst du es machen:

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,
};
17
mpen
/**
 * 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

Verwendungszweck:

<ul className="nav nav-tabs"> 
  <NavItem to='/home' index={true} >Home</NavItem>
  <NavItem to='/about'>About</NavItem>
</ul>
10
bryanyu

Anstelle von <Link /> benutze ich <NavLink /> und es funktioniert auch. 

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>
        );
    }
}
6
Dimang Chou
{/* 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>
4
Ken Berkeley

Gute Antwort.

Ändern Sie einfach das Folgende, damit es funktioniert ...

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

//Also link needs to be...
<NavItem to="/" onlyActiveOnIndex index={true}>Home</NavItem>
3
Matthew Berends

Versuchen Sie es mit Reactor-Router-Active-Component .

Ich konnte keine der vorherigen Antworten erhalten, die aufgrund von Inkompatibilitäten zwischen den Versionen reagieren oder TypeScript-Versionen (dies ist definitiv kein ausgereiftes Ökosystem) funktioniert, aber diese Komponente hat den Trick und kann bei Bedarf auf andere Elemente als li angewendet werden:

import activeComponent from 'react-router-active-component'
let NavItem = activeComponent('li');
...
<NavItem to='/' onlyActiveOnIndex>Home</NavItem>
<NavItem to='/generate-keywords'>Generate keywords</NavItem>
1
Erwin Mayer

Unter Verwendung von 15.1.0, Reakt-Router 2.5.0 und Bootstrap 3.3 (das ist weniger wichtig) habe ich diese Lösung entwickelt, um die Links zu aktivieren:

npm install --save classnames

npm install --save lodash

Die Komponente:

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;

Verwendungszweck:

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

Ich bin ein Anfänger von React, daher muss die oben genannte Lösung sicherlich verbessert werden und möglicherweise Annäherungsfehler enthalten. Es kann jedoch auch nützliche Informationen oder einen Ausgangspunkt für Interessierte enthalten. 

Feedback oder Anregungen sind mehr als willkommen. Vielen Dank! :)

1
Cristi Draghici

Mit React Router v4 habe ich es nur zur Wirkung gebracht, indem die <li>-Tags in die NavLink-Komponente aufgenommen wurden. Die Lösungen, bei denen die <li>-Tags die Links umschließen, führten dazu, dass der HOME <li>-Tag immer die active-Klasse hat.

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

Ich habe die CSS-Selektoren li und a entsprechend angepasst.

0
Steve Breese

Ich verwende React Router v4.2 und konnte den Verweis auf das Routerobjekt nicht von der Wrapping-Komponente abrufen, da der Kontext nicht verfügbar ist.

Das hat nicht funktioniert:

const { router } = this.context

Ich mag @ mpens answer , aber ich verwende verschachtelte Routen und möchte nicht die Datei ändern, in der ich die Routingkomponente definiert habe.

Was ich getan habe, ist den location.pathname mit zu vergleichen:

const NavItem = withRouter((props) => {
const { to, children, location } = props;
return (
    <li className={location.pathname == to ? 'active' : null}>
        <Link to={to}>{children}</Link >
    </li>
)});
0
Jernej Gorički