[英]react-router: How to disable a <Link>, if its active?
我如何禁用 react-router 中的<Link>
,如果它的 URL 已經激活? 例如,如果我的 URL 在單擊<Link>
時不會改變,我想完全阻止單擊或呈現<span>
而不是<Link>
。
我想到的唯一解決方案是使用activeClassName
(或activeStyle
)並設置pointer-events: none;
,但我寧願使用適用於 IE9 和 IE10 的解決方案。
您可以使用 CSS 的pointer-events
屬性。 這將適用於大多數瀏覽器。 例如你的JS代碼:
class Foo extends React.Component {
render() {
return (
<Link to='/bar' className='disabled-link'>Bar</Link>
);
}
}
和 CSS:
.disabled-link {
pointer-events: none;
}
鏈接:
附加的如何禁用 HTML 鏈接答案建議同時使用disabled
和pointer-events: none
以獲得最大的瀏覽器支持。
a[disabled] {
pointer-events: none;
}
鏈接到源:如何禁用鏈接
我不會問您為什么想要這種行為,但我想您可以將<Link />
包裝在您自己的自定義鏈接組件中。
<MyLink to="/foo/bar" linktext="Maybe a link maybe a span" route={this.props.route} />
class MyLink extends Component {
render () {
if(this.props.route === this.props.to){
return <span>{this.props.linktext}</span>
}
return <Link to={this.props.to}>{this.props.linktext}</Link>
}
}
(ES6,但您可能已經大致了解了...)
這對我有用:
<Link to={isActive ? '/link-to-route' : '#'} />
另一種可能性是如果已經在同一路徑上單擊,則禁用單擊事件。 這是一個適用於 react-router v4的解決方案。
import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
class SafeLink extends Component {
onClick(event){
if(this.props.to === this.props.history.location.pathname){
event.preventDefault();
}
// Ensure that if we passed another onClick method as props, it will be called too
if(this.props.onClick){
this.props.onClick();
}
}
render() {
const { children, onClick, ...other } = this.props;
return <Link onClick={this.onClick.bind(this)} {...other}>{children}</Link>
}
}
export default withRouter(SafeLink);
然后您可以將您的鏈接用作(來自Link
任何額外道具都可以使用):
<SafeLink className="some_class" to="/some_route">Link text</SafeLink>
具有禁用功能的React Router NavLink 的所有優點。
import React from "react"; // v16.3.2
import { withRouter, NavLink } from "react-router-dom"; // v4.2.2
export const Link = withRouter(function Link(props) {
const { children, history, to, staticContext, ...rest } = props;
return <>
{history.location.pathname === to ?
<span>{children}</span>
:
<NavLink {...{to, ...rest}}>{children}</NavLink>
}
</>
});
React Router 的Route
組件具有三種不同的方式來基於當前路由呈現內容。 雖然component
最常用於僅在匹配期間顯示組件,但children
組件接受({match}) => {return <stuff/>}
回調,即使路由不匹配,它也可以呈現匹配的內容匹配。
我創建了一個 NavLink 類,它用一個跨度替換一個鏈接,並在它to
路由處於活動狀態時添加一個類。
class NavLink extends Component {
render() {
var { className, activeClassName, to, exact, ...rest } = this.props;
return(
<Route
path={to}
exact={exact}
children={({ match }) => {
if (match) {
return <span className={className + " " + activeClassName}>{this.props.children}</span>;
} else {
return <Link className={className} to={to} {...rest}/>;
}
}}
/>
);
}
}
然后像這樣創建一個導航鏈接
<NavLink to="/dashboard" className="navlink" activeClassName="active">
React Router 的 NavLink做了類似的事情,但它仍然允許用戶點擊鏈接並推送歷史記錄。
基於 nbeuchat 的答案和組件 - 我創建了一個自己的改進版本的組件,它覆蓋了我的項目的react router's
Link
組件。
在我的情況下,我必須允許將對象傳遞to
prop(如本機react-router-dom
鏈接所做的那樣),我還添加了對search query
和hash
以及pathname
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Link as ReactLink } from 'react-router-dom';
import { withRouter } from "react-router";
const propTypes = {
to: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.object]),
location: PropTypes.object,
children: PropTypes.node,
onClick: PropTypes.func,
disabled: PropTypes.bool,
staticContext: PropTypes.object
};
class Link extends Component {
handleClick = (event) => {
if (this.props.disabled) {
event.preventDefault();
}
if (typeof this.props.to === 'object') {
let {
pathname,
search = '',
hash = ''
} = this.props.to;
let { location } = this.props;
// Prepend with ? to match props.location.search
if (search[0] !== '?') {
search = '?' + search;
}
if (
pathname === location.pathname
&& search === location.search
&& hash === location.hash
) {
event.preventDefault();
}
} else {
let { to, location } = this.props;
if (to === location.pathname + location.search + location.hash) {
event.preventDefault();
}
}
// Ensure that if we passed another onClick method as props, it will be called too
if (this.props.onClick) {
this.props.onClick(event);
}
};
render() {
let { onClick, children, staticContext, ...restProps } = this.props;
return (
<ReactLink
onClick={ this.handleClick }
{ ...restProps }
>
{ children }
</ReactLink>
);
}
}
Link.propTypes = propTypes;
export default withRouter(Link);
解決此問題的另一種選擇是使用ConditionalWrapper
組件,該組件根據條件呈現<Link>
標記。
這是我基於此博客使用的ConditionalWrapper
組件https://blog.hackages.io/conditionally-wrap-an-element-in-react-a8b9a47fab2 :
const ConditionalWrapper = ({ condition, wrapper, children }) =>
condition ? wrapper(children) : children;
export default ConditionalWrapper
這就是我們使用它的方式:
const SearchButton = () => {
const {
searchData,
} = useContext(SearchContext)
const isValid = () => searchData?.search.length > 2
return (<ConditionalWrapper condition={isValid()}
wrapper={children => <Link href={buildUrl(searchData)}>{children}</Link>}>
<a
className={`ml-auto bg-${isValid()
? 'primary'
: 'secondary'} text-white font-filosofia italic text-lg md:text-2xl px-4 md:px-8 pb-1.5`}>{t(
'search')}</a>
</ConditionalWrapper>
)
}
此解決方案不呈現Link
元素,也避免了代碼重復。
... const [isActive, setIsActive] = useState(true); ...
你可以試試這個,這對我有用。
我認為您應該將 atrtribute to=null設置為禁用鏈接。
如果它適合你的設計,在它上面放一個 div,然后操作 z-index。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.