如何将活动类添加到 React Router 的链接?
Posted
技术标签:
【中文标题】如何将活动类添加到 React Router 的链接?【英文标题】:How do I add an active class to a Link from 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>
我想在包装元素<li>
上将活动路径的类设置为active
。我看到还有其他解决方案可以展示如何做到这一点,例如Conditionally set active class on menu using react router current route,但是我认为这不是将包装器上的活动类设置为Link
的最佳方式。
我也找到了https://github.com/insin/react-router-active-component,但感觉没必要。
在 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
公开的activeStyle
或activeClassName
。周围有一些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>
);
【讨论】:
<li class=homeClass> ... </li>
更改 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 导航栏,因为它需要在 <li class="nav-item">
上而不是在锚标记上的 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';
&
<NavLink to="/Home" activeClassName="active">Home</NavLink>
【讨论】:
【参考方案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>
NavLink
的innerRef
属性接受回调函数,它将接收 DOM 节点作为参数。您可以使用任何可能的 DOM 操作,在这种情况下,只需将父元素 (<li>
) 设置为具有相同的类:
const setParentAsActive = node =>
if (node)
node.parentNode.className = node.className;
;
缺点:
<a>
将有不必要的 is-active
类(因为您只需要 <li>
),或者您可以在回调函数中删除该类。
如果您更改元素结构,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 <NavLink> outside a <Router>
【参考方案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,因为它具有这个活动类属性。
先导入
import NavLink from 'react-router-dom';
使用 activeClassName 获取活动类属性。
<NavLink to="/" activeClassName="active">
Home
</NavLink>
<NavLink to="/store" activeClassName="active">
Store
</NavLink>
<NavLink to="/about" activeClassName="active">
About Us
</NavLink>
通过属性 active 在 css 中为您的类设置样式。
.active
color:#fcfcfc;
【讨论】:
这行得通,谢谢,找到了关闭 Home 始终处于活动状态的解决方案:***.com/questions/51214763/…【参考方案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>
【讨论】:
这并没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review 从“react-router-dom”导入 NavLink ; @AbhishekDutt 我希望这会有所帮助.. ***.com/a/70359939/9166529【参考方案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>
我只是使用了NavLink
和activeClassName
没有将其包装在任何组件或其他东西中,但我的代码仍然有效:)
【讨论】:
以上是关于如何将活动类添加到 React Router 的链接?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Redux-Router + React-Router 将基本 URL 添加到应用程序
react-router:如果 <Link> 处于活动状态,如何禁用它?
使用 create-react-app 将 react-router-dom 添加到 react 应用程序时,为啥玩笑测试会中断
如何添加将使用 react-router-dom 渲染组件的路由?