如何从 React Router 添加活动 class 到 Link?

How do I add an active class to a Link from React Router?

我使用 Link 创建了一个 bootstrap 风格的边栏。这是我的代码片段:

<ul className="sidebar-menu">
  <li className="header">MAIN NAVIGATION</li>
  <li><Link to="dashboard"><i className="fa fa-dashboard"></i> <span>Dashboard</span></Link></li>
  <li><Link to="email_lists"><i className="fa fa-envelope-o"></i> <span>Email Lists</span></Link></li>
  <li><Link to="billing"><i className="fa fa-credit-card"></i> <span>Buy Verifications</span></Link></li>
</ul>

我想在包装元素 <li> 上将活动路径的 class 设置为 active。我看到还有其他解决方案展示了如何像 那样执行此操作,但是我认为这不是将包装器上的活动 class 设置为 Link 的最佳方法].

我也找到了https://github.com/insin/react-router-active-component但是感觉没有必要

在 React Router 中,这是可能的还是我需要使用外部解决方案?

在 Link 组件上,您现在可以添加 activeClassName 或设置 activeStyle.

这些使您可以轻松地向当前活动的 link 添加样式。


以前,您可以使用以下逻辑创建一个像 Link 的包装器一样工作的自定义组件。

在名为 nav_link.js

的文件中
import React from 'react';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';

class NavLink extends React.Component {
    render() {
        var isActive = this.context.router.route.location.pathname === this.props.to;
        var className = isActive ? 'active' : '';

        return(
            <Link className={className} {...this.props}>
                {this.props.children}
            </Link>
        );
    }
}

NavLink.contextTypes = {
    router: PropTypes.object
};

export default NavLink;

并在您的组件中按以下方式使用它:

...
import NavLink from "./nav_link";
.....

<nav>
    <ul className="nav nav-pills pull-right">
        <NavLink to="/">
            <i className="glyphicon glyphicon-home"></i> <span>Home</span>
        </NavLink>
        <NavLink to="about">
            <i className="glyphicon glyphicon-camera"></i> <span>About</span>
        </NavLink>
    </ul>
</nav>

答案更新为 ES6:

import React, { Component } from 'react';
import { Link } from 'react-router'

class NavLink extends Component {
    render() {
        let isActive = this.context.router.isActive(this.props.to, true);
        let className = isActive ? "active" : "";

        return (
            <li className={className}>
                <Link {...this.props}/>
            </li>
        );
    }
}

NavLink.contextTypes = {
    router: React.PropTypes.object
};

export default NavLink;

然后按上述方法使用它。

我不喜欢创建自定义组件的想法,因为如果您有不同的包装元素,您将不得不创建另一个自定义组件等。而且,这也太过分了。所以我只是用 css 和 activeClassName:

<li className="link-wrapper">  <!-- add a class to the wrapper -->
  <Link to="something" activeClassName="active">Something</Link>
</li>

然后再添加一些 css:

li.link-wrapper > a.active {
    display: block;
    width: 100%;
    height:100%;
    color: white;
    background-color: blue;
}

从技术上讲,这不会为 li 设置样式,但它会使锚点填充 li 并为其设置样式。

这是我的方式,使用道具中的位置。 我不知道,但 history.isActive 对我来说是未定义的

export default class Navbar extends React.Component {
render(){
const { location } = this.props;

const homeClass = location.pathname === "/" ? "active" : "";
const aboutClass = location.pathname.match(/^\/about/) ? "active" : "";
const contactClass = location.pathname.match(/^\/contact/) ? "active" : "";


return (
<div>
      <ul className="nav navbar-nav navbar-right">
        <li className={homeClass}><Link to="/">Home</Link></li>
        <li className={aboutClass}><Link to="about" activeClassName="active">About</Link></li>
        <li className={contactClass}><Link to="contact" activeClassName="active">Contact</Link></li>
      </ul>

</div>
    );}}

你实际上可以复制里面的东西 NavLink 像这样

const NavLink = ( {
  to,
  exact,
  children
} ) => {

  const navLink = ({match}) => {

    return (
      <li class={{active: match}}>
        <Link to={to}>
          {children}
        </Link>
      </li>
    )

  }

  return (
    <Route
      path={typeof to === 'object' ? to.pathname : to}
      exact={exact}
      strict={false}
      children={navLink}
    />
  )
}

只需查看 NavLink 源代码并删除不需要的部分 ;)

React-Router V4 附带一个开箱即用的 NavLink 组件

要使用,只需将 activeClassName 属性设置为您已适当设置样式的 class,或直接将 activeStyle 设置为您想要的样式。有关详细信息,请参阅 the docs

<NavLink
  to="/hello"
  activeClassName="active"
>Hello</NavLink>

当您使用 react-redux 进行状态管理并且一些父组件是 [= 时,Vijey 的回答有点问题34=] 到 redux 存储。 activeClassName仅在页面刷新时应用到Link,不会随着当前路由的变化而动态应用

这与 react-redux 的连接功能有关,因为它抑制了上下文更新。要禁用抑制上下文更新,您可以在调用 connect() 方法时设置 pure: false,如下所示:

//your component which has the custom NavLink as its child. 
//(this component may be the any component from the list of 
//parents and grandparents) eg., header

function mapStateToProps(state) {
  return { someprops: state.someprops }
}

export default connect(mapStateToProps, null, null, {
  pure: false
})(Header);

检查这里的问题:reactjs#470

在此处查看 pure: false 文档:docs

使用 react-router-dom@4.3.1(尽管我猜任何 4.x.x 都应该),我们可以使用 withRouter HOC 来完成此操作。例如,我想实现 Bootstrap 导航栏,因为它需要 <li class="nav-item"> 而不是锚标记上的 class 或 active,我制作了一个名为 NavItem封装单个li.nav-item。实现如下:

import React from "react";
import { Link, withRouter } from "react-router-dom";

const NavItem = ({ isActive, to, label }) => {
  let classes = ["nav-item"];
  if (isActive) classes.push("active");

  return (
    <li className={classes.join(" ")}>
      <Link className="nav-link" to={to}>
        {label}
      </Link>
    </li>
  );
};

export default withRouter(({ location, ...props }) => {
  const isActive = location.pathname === props.to;

  console.log(location.pathname, props.to);

  return <NavItem {...props} isActive={isActive} />;
});

如您所见,NavItem 只是一个无状态功能组件,它需要一个 isActive 属性来确定是否应添加 active class。现在,要随着位置的变化更新这个道具,我们可以使用 withRouter HOC。您可以将任何组件传递给此函数,它会在其道具中为它提供 { match, location, history } 个对象以及您传递的对象。在这里,我正在创建一个内联功能组件,它接收这些对象并使用 location.pathname 属性 确定当前 link 是否是活动的。这将为我们提供 Boolean,我们可以 return 将 NavItemisActive 设置为我们使用 location.pathname.

计算的值

可以找到一个这样的工作示例 here。如果有更简单的方法,请告诉我。

从 react-router-dom@4.3.1 开始,我们可以轻松地使用带有 activeClassName 的 NavLink 而不是 Link。示例:

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';

class NavBar extends Component {
  render() {
    return (
      <div className="navbar">
        <ul>
          <li><NavLink to='/1' activeClassName="active">1</NavLink></li>
          <li><NavLink to='/2' activeClassName="active">2</NavLink></li>
          <li><NavLink to='/3' activeClassName="active">3</NavLink></li>
        </ul>
      </div>
    );
  }
}

然后在您的 CSS 文件中:

.navbar li>.active {
  font-weight: bold;
}

NavLink 将根据当前 URL.

将您的自定义样式属性添加到呈现的元素中

文件是here

在活动导航元素上设置 class

import { NavLink } from 'react-router-dom';

&

<NavLink to="/Home" activeClassName="active">Home</NavLink>

这很容易做到,react-router-dom提供了所有。

import React from 'react';
import { matchPath, withRouter } from 'react-router';
    
class NavBar extends React.Component {
  render(){
    return(
       <ul className="sidebar-menu">
      <li className="header">MAIN NAVIGATION</li>
      <li className={matchPath(this.props.location.pathname, { path: "/dashboard" }) ? 'active' : ''}><Link to="dashboard"><i className="fa fa-dashboard"></i> 
        <span>Dashboard</span></Link></li>
      <li className={matchPath(this.props.location.pathname, { path: "/email_lists" }) ? 'active' : ''}><Link to="email_lists"><i className="fa fa-envelope-o"></i> 
        <span>Email Lists</span></Link></li>
      <li className={matchPath(this.props.location.pathname, { path: "/billing" }) ? 'active' : ''}><Link to="billing"><i className="fa fa-credit-card"></i> 
        <span>Buy Verifications</span></Link></li>
    </ul>
      )
   }
}
    
export default withRouter(NavBar);

使用 withRouter() HOC 包装您的导航组件将为您的组件提供一些道具: 1.匹配 2. 历史 3. 地点

这里我使用了 react-router 中的 matchPath() 方法来比较路径并决定 'li' 标签是否应该得到 "active" class 名字与否。我正在从 this.props.location.pathname.

访问该位置

当我们的 link 被点击时,道具中的路径名称会发生​​变化,位置道具将得到更新 NavBar 也会得到 re-rendered 并且活动样式将得到应用

从路由器 v4 开始,我使用 'refs' 来设置父活动 class:

<ul>
  <li>
    <NavLink
      innerRef={setParentAsActive}
      activeClassName="is-active"
      to={link}
    >
    {text}
  </NavLink>
</ul>

NavLinkinnerRef 属性接受回调函数,它将接收 DOM 节点作为参数。您可以使用任何可能的 DOM 操作,在这种情况下只需将父元素 (<li>) 设置为具有相同的 class:

  const setParentAsActive = node => {
    if (node) {
      node.parentNode.className = node.className;
    }
  };

缺点:

  • <a> 将有不必要的 is-active class(因为你只需要 <li>),或者你可以在回调中删除这个 class功能
  • 如果更改元素结构,f.e。将 a 标记包裹在 span 中,您的回调将停止工作,但可以编写更复杂的 DOM 遍历函数
  • 你必须做一些DOM操作

只需使用 NavLink 而不是 Link。它会自动添加.active class。

<Nav className="mr-auto">
    <Nav.Link as={NavLink} to="/home">Home</Nav.Link>
    <Nav.Link as={NavLink} to="/users">Users</Nav.Link>
</Nav>

扩展@BaiJiFeiLong的回答,在link中添加一个active={} 属性:

<Nav.Link as={Link} to="/user" active={pathname.startsWith('/user')}>User</Nav.Link>

当任何路径以“/user”开头时,这将显示 User link 处于活动状态。为了在每次路径更改时更新,请在组件上包含 withRouter()

import React from 'react'
import { Link, withRouter } from 'react-router-dom'
import Navbar from 'react-bootstrap/Navbar'
import Nav from 'react-bootstrap/Nav'

function Header(props) {
    const pathname = props.location.pathname

    return (
        <Navbar variant="dark" expand="sm" bg="black">
            <Navbar.Brand as={Link} to="/">
                Brand name
            </Navbar.Brand>
            <Navbar.Toggle aria-controls="basic-navbar-nav" />
            <Navbar.Collapse id="basic-navbar-nav">
                <Nav className="mr-auto">
                    <Nav.Link as={Link} to="/user" active={pathname.startsWith('/user')}>User</Nav.Link>
                    <Nav.Link as={Link} to="/about" active={pathname.startsWith('/about')}>About</Nav.Link>
                </Nav>
            </Navbar.Collapse>
        </Navbar>
    )
}

export default withRouter(Header)   // updates on every new page

使用 Jquery 进行活动 link:

$(function(){
    $('#nav a').filter(function() {
        return this.href==location.href
    })
    .parent().addClass('active').siblings().removeClass('active')

    $('#nav a').click(function(){
        $(this).parent().addClass('active').siblings().removeClass('active')
    })
});

使用Jquery中指定的组件生命周期方法或文档就绪函数。

import React from 'react';
import {withRouter, Link} from "react-router-dom";

const SidenavItems = (props) => {
                                     // create simple list of links
    const items = [
        {
            type: "navItem",
            icon: "home",
            text: "Home",
            link: "/",
            restricted: false
        },
        {
            type: "navItem",
            icon: "user-circle",
            text: "My Profile",
            link: "/user",
            restricted: false
        },
        {
            type: "navItem",
            icon: "sign-in",
            text: "Login",
            link: "/login",
            restricted: false
        },
    ];

    const element = (item, i) => {  // create elements (Links)
                        // check if this is a current link on browser
        let active = "";

        if (props.location.pathname === item.link) {
            active = "active";
        }

        return (
            <div key={i} className={item.type}>
                <Link
                    to={item.link}
                    className={active} // className will be set to "active" 
                >                      // or ""
                    {item.text}
                </Link>
            </div>
        )
    };

    const showItems = () => {     // print elements
        return items.map((item, i) => {
            return element(item, i)
        })
    };

    return (
        <div>
            {showItems()}  // print all the links we created in list
        </div>
    )
};
export default withRouter(SidenavItems);

其中一种使用方式

当您使用功能组件时,请按照此处的说明进行操作。

  • 在您的组件中添加一个变量
  • 创建事件更改浏览器URLchange/or其他更改
  • 重新分配当前路径(URL)
  • 使用javascript匹配函数并设置为active或其他

这里使用上面的代码。

import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';

const NavItems = () => {
    let pathname = window.location.pathname;
    useEffect(() => {
        pathname = window.location.pathname;
    }, [window.location.pathname]);

    return (
        <>
            <li className="px-4">
                <Link to="/home" className={`${pathname.match('/home') ? 'link-active' : ''}`}>Home</Link>
            </li>
            <li className="px-4">
                <Link to="/about-me" className={`${pathname.match('/about-me') ? 'link-active' : ''}`}>About-me</Link>
            </li>
            <li className="px-4">
                <Link to="/skill" className={`${pathname.match('/skill') ? 'link-active' : ''}`}>Skill</Link>
            </li>
            <li className="px-4">
                <Link to="/protfolio" className={`${pathname.match('/protfolio') ? 'link-active' : ''}`}>Protfolio</Link>
            </li>
            <li className="pl-4">
                <Link to="/contact" className={`${pathname.match('/contact') ? 'link-active' : ''}`}>Contact</Link>
            </li>
        </>
    );
}

export default NavItems;

--- 谢谢 ---

当前 React Router 版本 5.2.0

activeStyle 是 NavLink 组件的 默认 css 属性react-router-dom

这样我们就可以编写自己的自定义 css 以使其成为 active.In 这个例子我将背景设为透明并且文本设为 bold.And 我将其存储在名为 [=] 的常量中17=]有效

    import React from "react";
    import { NavLink} from "react-router-dom";

    function nav() {

          const isActive = {
            fontWeight: "bold",
            backgroundColor: "rgba(255, 255, 255, 0.1)",
          };
    
    return (
          <ul className="navbar-nav mr-auto">
            <li className="nav-item">
              <NavLink className="nav-link" to="/Shop" activeStyle={isActive}>
                Shop
              </NavLink>
            </li>
          </ul>
          );

    export default nav;

使用 React Hooks。

import React, { useState } from 'react';

export const Table = () => {

const [activeMenu, setActiveMenu] = useState('transaction');

return(
<>
 <Link className="flex-1 mr-2">
          <a
            id="transaction"
            className={
              activeMenu == 'transaction'
                ? 'text-center block border border-blue-500 rounded py-2 px-4 bg-blue-500 hover:bg-blue-700 text-white'
                : 'text-center block border border-white rounded hover:border-gray-200 text-blue-500 hover:bg-gray-200 py-2 px-4'
            }
            href="#"
            onClick={() => {
              setActiveMenu('transaction');
            }}>
            Recent Transactions
          </a>
        </Link>
        <Link className="flex-1 mr-2">
          <a
            id="account"
            className={
              activeMenu == 'account'
                ? 'text-center block border border-blue-500 rounded py-2 px-4 bg-blue-500 hover:bg-blue-700 text-white'
                : 'text-center block border border-white rounded hover:border-gray-200 text-blue-500 hover:bg-gray-200 py-2 px-4'
            }
            href="#"
            onClick={() => {
              setActiveMenu('account');
            }}>
            Account Statement
          </a>
        </LInk>

</>
)
}

对我来说有用的是使用 NavLink,因为它有这个活动 class 属性.

  1. 先导入

    import { NavLink } from 'react-router-dom';
    
  2. 使用 activeClassName 获取活动 class 属性.

    <NavLink to="/" activeClassName="active">
     Home
    </NavLink>
    
    <NavLink to="/store" activeClassName="active">
     Store
    </NavLink>
    
    <NavLink to="/about" activeClassName="active">
     About Us
    </NavLink>
    
  3. 在 css 中设置您的 class 样式由 属性 激活。

    .active{
      color:#fcfcfc;
     }
    
<Navbar bg="light" expand="lg">
<Container>
    <Navbar.Brand>
        <Nav.Link as="{NavLink}" to="/">Brand Name</Nav.Link>
    </Navbar.Brand>
    <Navbar.Toggle aria-controls="basic-navbar-nav" />
    <Navbar.Collapse id="basic-navbar-nav">
        <nav className="me-auto">
            <Nav.Link as="{NavLink}" to="/" exact>Home</Nav.Link>
            <Nav.Link as="{NavLink}" to="/about">About</Nav.Link>
            <Nav.Link as="{NavLink}" to="/contact">Contact</Nav.Link>
            <NavDropdown title="Dropdown" id="basic-nav-dropdown">
                <Nav.Link as="{NavLink}" to="/page1">Dropdown Link 1</Nav.Link>
                <Nav.Link as="{NavLink}" to="/page2">Dropdown Link 2</Nav.Link>
                <Nav.Link as="{NavLink}" to="/page3">Dropdown Link 3</Nav.Link>
            </NavDropdown>
        </nav>
    </Navbar.Collapse>
</Container>

在 react-router-dom 文档中,您使用 navlink 而不是 link。 https://v5.reactrouter.com/web/api/NavLink

import { NavLink } from "react-router-dom"; 
<Nav>
  <NavLink exact activeClassName="active--link" to="/" className="your class" > Home </NavLink> 
 <NavLink exact to="/classes" activeClassName="active--link" className="your class" > Classes </NavLink>
</Nav>
<NavLink to="/hello" activeClassName="active">Hello</NavLink>

React Router v6:

来源:Active NavLink 类 与 React Router

您需要使用 className 属性,它现在接受一个函数并传递一个 isActive 布尔值 属性:

<NavLink
  to="users"
  className={({ isActive }) => (isActive ? 'active' : 'inactive')}
>
  Users
</NavLink>

这也非常适合添加多个 类,并且是 v6 beta 中的重大更改:

<NavLink
  to="users"
  className={({ isActive }) =>
    isActive ? 'bg-green-500 font-bold' : 'bg-red-500 font-thin'
  }
>
  Users
</NavLink>

阅读更多内容并进行现场演示:Active NavLink 类 with React Router

<NavLink to='/' activeClassName='active'>
        Home
</NavLink>

我只是使用了 NavLinkactiveClassName 而没有将其包装在任何组件或其他东西中,但我的代码仍然有效:)

在 React 路由器版本 6 中,我们通过 NavLink 完成它并设置它的类名 属性。

我们在这里指定了一个函数,每次路由更改时都会调用该函数。

   import { NavLink } from 'react-router-dom';
   
   import classes from './MainHeader.module.css';
   
   const MainHeader = () => {
     return (
       <header className={classes.header}>
         <nav>
           <ul>
             <li>
               <NavLink className={({isActive}) => isActive ? classes.active : ''} to='/welcome'>
                 Welcome
               </NavLink>
             </li>
             <li>
               <NavLink className={({isActive}) => isActive ? classes.active : ''} to='/products'>
                 Products
               </NavLink>
             </li>
           </ul>
         </nav>
       </header>
     );
   };
   
   export default MainHeader;

also, you can find a whole tutorial on it on this link

È=12=ÈтÈ=13=Èт@вшш=11=Èт w=10=sh
import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';

class NavBar extends Component {
  render() {
    return (
      <div className="navbar">
        <ul>
          <li><NavLink to='/1' activeClassName="active">1</NavLink></li>
          <li><NavLink to='/2' activeClassName="active">2</NavLink></li>
          <li><NavLink to='/3' activeClassName="active">3</NavLink></li>
        </ul>
      </div>
    );
  }
}

这适用于我的...