react-router: How to disable a <Link>, if its active?

How can I disable a <Link> in react-router, if its URL already active? E.g. if my URL wouldn't change on a click on <Link> I want to prevent clicking at all or render a <span> instead of a <Link>.

The only solution which comes to my mind is using activeClassName (or activeStyle) and setting pointer-events: none;, but I'd rather like to use a solution which works in IE9 and IE10.


Solution 1:

You can use CSS's pointer-events attribute. This will work with most of the browsers. For example your JS code:

class Foo extends React.Component {
  render() {
    return (
      <Link to='/bar' className='disabled-link'>Bar</Link>
    );
  }
}

and CSS:

.disabled-link {
  pointer-events: none;
}

Links:

  • pointer-events CSS property
  • How to disable HTML links

The How to disable HTML links answer attached suggested using both disabled and pointer-events: none for maximum browser-support.

a[disabled] {
    pointer-events: none;
}

Link to source: How to disable Link

Solution 2:

This works for me:

<Link to={isActive ? '/link-to-route' : '#'} />

Solution 3:

I'm not going to ask why you would want this behavior, but I guess you can wrap <Link /> in your own custom link component.

<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, but you probably get the general idea...)

Solution 4:

Another possibility is to disable the click event if clicking already on the same path. Here is a solution that works with 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);

You can then use your link as (any extra props from Link would work):

<SafeLink className="some_class" to="/some_route">Link text</SafeLink>