【问题标题】:React Router v4 setting activeClass on parentReact Router v4 在父级上设置 activeClass
【发布时间】:2017-08-16 06:59:44
【问题描述】:

对反应路由器不太熟悉,但我需要 NavLink 的功能来在父 li 元素上设置活动类,而不是 a 元素。

为了实现这一点,我只是查看了NavLink 的源代码并将其复制到一个新元素中。 (使用 typescript 的例子,但和 js 差不多)

import * as React from 'react';
import { Link, withRouter, Route } from 'react-router-dom';


class LiNavLink extends React.Component<any, {}> {
    render() {
        const {to,exact, strict, activeClassName, className, activeStyle, style, isActive: getIsActive, ...rest } = this.props;
        return (
            <Route
                path={typeof to === 'object' ? to.pathname : to}
                exact={exact}
                strict={strict}
                children={({ location, match }) => {
                    const isActive = !!(getIsActive ? getIsActive(match, location) : match)

                    return (
                        <li 
                            className={isActive ? [activeClassName, className].join(' ') : className}
                            style={isActive ? { ...style, ...activeStyle } : style}>
                            <Link
                                to={to}
                                {...rest}
                            />
                        </li>
                    )
                }}
            />
        );
    }
}

export default LiNavLink;

然后是用法:

<ul>
   <LiNavLink activeClassName='active' exact={true} strict to="/example"><span>Active</span></LiNavLink>
   <LiNavLink activeClassName='active' exact={true} strict to="/example/archived"><span>Archived</span></LiNavLink>
</ul>

我正在使用HashRouter,由于某种我无法弄清楚的原因,当路线改变时它不会更新,只有当我硬“刷新”页面时它才会更新它应该如何更新。

我相信它永远不会更新,因为道具永远不会改变?所以它不知道自己更新?

我怎样才能让它更新?还是我的问题在其他地方?

【问题讨论】:

  • 你找到答案了吗?我也想要这个功能。
  • @JimFactor 是的,上面的解决方案有效,我的问题是有另一个组件阻止更新。我用这个文档github.com/ReactTraining/react-router/blob/master/packages/…
  • 谢谢,原始代码有效,我只是添加了一个aClassName 来传递&lt;a&gt; 元素的类名

标签: reactjs react-router-v4 react-router-dom


【解决方案1】:

检查这个

class LiNavLink extends React.Component<NavLinkProps> {
    render() {
        return (
            <Route exact={this.props.exact} path={this.props.to.toString()}>
                {
                    ({ match }) =>
                        <li className={match ? 'active' : undefined}>
                            <Link to={this.props.to} >
                               {this.props.children}
                            </Link>
                        </li>
                }
            </Route>
        );
    }
}

【讨论】:

    【解决方案2】:

    经过多次尝试,在 v4 中。

    这是我的工作代码。

    import React, { Component } from "react";
    import logo from "../../logo.svg";
    import { Link, withRouter } from "react-router-dom";
    import PropTypes from "prop-types";
    
    class Navbar extends Component {
      static propTypes = {
        match: PropTypes.object.isRequired,
        location: PropTypes.object.isRequired,
        history: PropTypes.object.isRequired
      };
    
      state = {};
    
      getNavLinkClass = path => {
        return this.props.location.pathname === path
          ? "nav-item active"
          : "nav-item";
      };
      render() {
        return (
          <nav className="navbar navbar-expand-lg navbar-dark bg-dark">
            <Link className="navbar-brand" to="/">
              <img
                src={logo}
                width="30"
                height="30"
                className="d-inline-block align-top"
                alt=""
              />
              Utility
            </Link>
            <button
              className="navbar-toggler"
              type="button"
              data-toggle="collapse"
              data-target="#navbarNav"
              aria-controls="navbarNav"
              aria-expanded="false"
              aria-label="Toggle navigation"
            >
              <span className="navbar-toggler-icon" />
            </button>
            <div className="collapse navbar-collapse" id="navbarNav">
              <ul className="navbar-nav">
                <li className={this.getNavLinkClass("/")}>
                  <Link className="nav-link" to="/">
                    Home
                  </Link>
                </li>
                <li className={this.getNavLinkClass("/age-counter")}>
                  <Link className="nav-link" to="/age-counter">
                    Age Counter
                  </Link>
                </li>
              </ul>
            </div>
          </nav>
        );
      }
    }
    
    export default withRouter(Navbar);
    

    演示工作Code Sandbox

    【讨论】:

      【解决方案3】:

      我只是从反应开始,所以不确定这是否是最佳实践,但在浏览了路由器 v4 文档后,我使用了 withRouter props -> location.pathname 并将其与我的路由进行了比较。

      这里是 Navigation.js:

      import React from 'react';
      import { withRouter } from 'react-router-dom';
      import NavLink from '../General/NavLink';
      
      const activeClass = (path, link) => {
          if (path === link) {
              return true;
          }
          return false;
      };
      
      const Navigation = props => {
          const { location } = props;
          return (
              <ul className="menu menu--main nano-content">
                  <NavLink
                      to="/"
                      parentClass={
                          activeClass(location.pathname, '/')
                              ? 'menu__item menu__item--active'
                              : 'menu__item'
                      }
                      linkClass="menu__link effect effect--waves"
                  >
                      Dashboard
                  </NavLink>
                  <NavLink
                      to="/users"
                      parentClass={
                          activeClass(location.pathname, '/users')
                              ? 'menu__item menu__item--active'
                              : 'menu__item'
                      }
                      linkClass="menu__link effect effect--waves"
                  >
                      Users
                  </NavLink>
                  <NavLink
                      to="/projects"
                      parentClass={
                          activeClass(location.pathname, '/projects')
                              ? 'menu__item menu__item--active'
                              : 'menu__item'
                      }
                      linkClass="menu__link effect effect--waves"
                  >
                      Projects
                  </NavLink>
                  <NavLink
                      href="http://google.com"
                      parentClass="menu__item"
                      linkClass="menu__link effect effect--waves"
                  >
                      Google
                  </NavLink>
              </ul>
          );
      };
      
      export default withRouter(Navigation);
      

      从那里您可以在子组件上使用父类和子类。

      【讨论】:

        【解决方案4】:

        我发现通过使用 CSS,您可以通过在活动类中设置 display:block; 来使活动链接扩展以填充其父 &lt;li&gt; 元素。

        例如,如果我们的链接是:

        <li>
          <NavLink to="/overview" className=styles.sideLink activeClassName=styles.sideLinkSelected>
            Overview 
          </NavLink>
        </li>
        

        那么我们的 CSS 将是:

        &__sideLinkSelected
        {
          background-color: blue;
          display:block;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-10-26
          • 2018-01-10
          • 2017-09-21
          • 2017-05-16
          • 2017-08-07
          • 2018-11-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多