【问题标题】:How do I add an active class to a Link from React Router?如何将活动类添加到 React Router 的链接?
【发布时间】:2016-03-28 20:38:23
【问题描述】:

我使用Link 创建了一个引导式侧边栏。这是我的代码的 sn-p:

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

我想在包装元素&lt;li&gt; 上将活动路径的类设置为active。我看到还有其他解决方案可以展示如何做到这一点,例如Conditionally set active class on menu using react router current route,但是我认为这不是将包装器上的活动类设置为Link 的最佳方式。

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

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

【问题讨论】:

    标签: react-router


    【解决方案1】:

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

    这些使您可以轻松地将样式添加到当前活动的链接。


    以前,您可以使用以下逻辑创建一个自定义组件,该组件类似于链接的包装器。

    在名为 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>
    

    【讨论】:

    • NavLink 组件中的内容类型应该是静态属性而不是实例属性。请更正。
    • 为什么不使用react-router 公开的activeStyleactiveClassName。周围有一些documentation
    • 这似乎不再适用于 react-router v4.0.0,因为 router.isActive 不再存在。见:github.com/react-bootstrap/react-router-bootstrap/issues/186
    • 使用 react-router 3.0.0 ,得到TypeError: Cannot read property 'location' of undefined
    • 是的,它应该是公认的答案。它对我来说效果很好!但是,配置不仅仅是这些步骤。对我来说,它只是确保我的导航中的 组件都被这个包裹了。还有其他步骤使这项工作在宏伟的计划中发挥作用。稍后有空我会在这里分享。
    【解决方案2】:

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

    然后如上所述使用它。

    【讨论】:

    • this.context.route 未定义我(较新版本?),您可以使用withRouter 函数在参数中传递路由器
    【解决方案3】:

    我不喜欢创建自定义组件的想法,因为如果您有不同的包装元素,您将不得不创建另一个自定义组件等。而且,这只是矫枉过正。所以我只是用 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 并设置它的样式。

    【讨论】:

      【解决方案4】:

      这是我的方式,使用来自道具的位置。 我不知道,但 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>
          );}}
      

      【讨论】:

      • &lt;li class={homeClass}&gt; ... &lt;/li&gt; 更改 class=> 类名
      【解决方案5】:

      您实际上可以复制 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 源代码并删除不需要的部分;)

      【讨论】:

        【解决方案6】:

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

        要使用,只需将activeClassName 属性设置为您已适当样式的类,或直接将activeStyle 设置为您想要的样式。详情请见the docs

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

        【讨论】:

        • 这是在 wrapper 到链接。
        • 这会输出一个锚标记。 OP 想要一些能输出列表项的东西。
        • 这真的有效吗?我试过了,但它不适合我。
        【解决方案7】:

        当您使用 react-redux 进行状态管理并且某些父组件 'connected' 到还原商店。 activeClassName 仅在页面刷新时应用到 Link,不会随着当前路由的变化而动态应用。

        这与 react-redux 的 connect 函数有关,因为它抑制了上下文更新。要禁用对上下文更新的抑制,您可以在调用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

        【讨论】:

          【解决方案8】:

          使用react-router-dom@4.3.1(尽管我猜应该可以使用任何4.x.x),我们可以使用withRouter HOC 来完成此操作。例如,我想实现 Bootstrap 导航栏,因为它需要在 &lt;li class="nav-item"&gt; 上而不是在锚标记上的 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 类。现在,要随着位置的变化更新这个道具,我们可以使用withRouter HOC。您可以将任何组件传递给此函数,它会在其 props 中为它提供 { match, location, history } 对象以及您传递的对象。在这里,我正在创建一个内联功能组件,它接收这些对象并使用location.pathname 属性确定当前链接是否为活动链接。这将给我们一个Boolean,我们可以返回NavItem以及isActive设置为我们使用location.pathname计算的值。

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

          【讨论】:

            【解决方案9】:

            从 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

            【讨论】:

              【解决方案10】:

              在活动导航元素上设置类

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

              &

              &lt;NavLink to="/Home" activeClassName="active"&gt;Home&lt;/NavLink&gt;

              【讨论】:

                【解决方案11】:

                这很容易做到,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' 标签是否应该获得“活动”类名。我从 this.props.location.pathname 访问该位置。

                当我们的链接被点击时,props 中的路径名称会发生​​变化,并且位置 props 会得到更新,NavBar 也会被重新渲染,并且活动样式会被应用

                【讨论】:

                  【解决方案12】:

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

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

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

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

                  缺点:

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

                  【讨论】:

                    【解决方案13】:

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

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

                    【讨论】:

                      【解决方案14】:

                      扩展@BaiJiFeiLong 的答案,在链接中添加active={} 属性:

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

                      当任何路径以“/user”开头时,这将显示User 链接处于活动状态。要在每次路径更改时更新此内容,请在组件中包含 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
                      

                      【讨论】:

                        【解决方案15】:

                        使用 Jquery 进行活动链接:

                        $(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 中指定的组件生命周期方法或文档准备功能。

                        【讨论】:

                        • 老兄,React with JQuery 方法的问题回答错了
                        【解决方案16】:

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

                        【讨论】:

                        • 您好!虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
                        • 嗨!我添加了一些 cmets
                        【解决方案17】:

                        你可以使用它的一种方式

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

                        • 在组件中添加变量
                        • 创建事件更改浏览器 URL 更改/或其他更改
                        • 重新分配当前路径(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;
                        

                        --- 谢谢---

                        【讨论】:

                        • 是否可以匹配 2 条路径?因此,例如,如果其中一个路径为真,则将类设置为活动类似这样的内容:${pathname.match('/protfolio' || /anotherpath)
                        • @LyubomirIvanovValchev 您可以使用如下逻辑运算符: (${pathname.match('/protfolio') || ${pathname.match("/anotherpath") )? '活动网址' : ' '
                        • 如果我们在单个选项卡上有更多路径,您能否提出更好的方法
                        【解决方案18】:

                        当前 React 路由器版本 5.2.0

                        activeStyle 是从 react-router-dom

                        导入的 NavLink 组件的默认 css 属性

                        这样我们就可以编写自己的自定义 css 来使其处于活动状态。在这个例子中,我将背景设置为透明,将文本设置为粗体。并将其存储在一个名为 isActive

                        的常量中
                            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;
                        
                        

                        【讨论】:

                        • 抛出错误:Error: Invariant failed: You should not use &lt;NavLink&gt; outside a &lt;Router&gt;
                        【解决方案19】:

                        使用 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>
                        
                        </>
                        )
                        }
                        

                        【讨论】:

                          【解决方案20】:

                          对我来说有效的是使用 NavLink,因为它具有这个活动类属性。

                          1. 先导入

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

                            <NavLink to="/" activeClassName="active">
                             Home
                            </NavLink>
                            
                            <NavLink to="/store" activeClassName="active">
                             Store
                            </NavLink>
                            
                            <NavLink to="/about" activeClassName="active">
                             About Us
                            </NavLink>
                            
                          3. 通过属性 active 在 css 中为您的类设置样式。

                            .active{
                              color:#fcfcfc;
                             }
                            

                          【讨论】:

                          【解决方案21】:
                          <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>
                          

                          【讨论】:

                          • 一些解释会使这成为一个更好的答案。
                          【解决方案22】:

                          在 react-router-dom 文档中,您使用 navlink 而不是链接。 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>
                          
                          

                          【讨论】:

                          【解决方案23】:

                          React 路由器 v6:

                          来源:Active NavLink Classes with React Router

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

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

                          这也非常适合添加多个类,并且是 v6 测试版中的一项重大更改:

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

                          阅读更多内容和现场演示:Active NavLink Classes with React Router

                          【讨论】:

                            【解决方案24】:
                            <NavLink to='/' activeClassName='active'>
                                    Home
                            </NavLink>
                            

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

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2010-12-29
                              • 2013-08-15
                              • 2017-04-29
                              • 1970-01-01
                              • 2017-08-31
                              • 2019-08-03
                              • 2018-09-05
                              • 1970-01-01
                              相关资源
                              最近更新 更多