Search code examples
javascripthtmlreactjsreact-routerreactstrap

Using Tag to pass a attribute inside NavLink reactstrap component


Can someone help me to figure out what can be the significance of passing the Link tag inside the NavLink component like this :

<NavLink tag={Link} to="/components/" activeClassName="active">Components</NavLink>

The code for NavLink (reactstrap component) is given below :

import PropTypes from 'prop-types';
import classNames from 'classnames';
import { mapToCssModules, tagPropType } from './utils';

const propTypes = {
  tag: tagPropType,
  innerRef: PropTypes.oneOfType([PropTypes.object, PropTypes.func, PropTypes.string]),
  disabled: PropTypes.bool,
  active: PropTypes.bool,
  className: PropTypes.string,
  cssModule: PropTypes.object,
  onClick: PropTypes.func,
  href: PropTypes.any,
};

const defaultProps = {
  tag: 'a',
};

class NavLink extends React.Component {
  constructor(props) {
    super(props);

    this.onClick = this.onClick.bind(this);
  }

  onClick(e) {
    if (this.props.disabled) {
      e.preventDefault();
      return;
    }

    if (this.props.href === '#') {
      e.preventDefault();
    }

    if (this.props.onClick) {
      this.props.onClick(e);
    }
  }

  render() {
    let {
      className,
      cssModule,
      active,
      tag: Tag,
      innerRef,
      ...attributes
    } = this.props;

    const classes = mapToCssModules(classNames(
      className,
      'nav-link',
      {
        disabled: attributes.disabled,
        active: active
      }
    ), cssModule);

    return (
      <Tag {...attributes} ref={innerRef} onClick={this.onClick} className={classes} />
    );
  }
}

NavLink.propTypes = propTypes;
NavLink.defaultProps = defaultProps;

export default NavLink;

Here you can see that the NavLink returns a component wrapped inside the tag we passed as props. The basic function of Link (react-router component) i.e routing the components is not accomplished here. So passing it as a prop for NavLink is confusing me.


Solution

  • I believe it's a how they provide re-usability over the Link component coming from the react-router or maybe any other Link component you want to use! what we basically have is:

    // react-router/Link
    <Link to="/about">About</Link>
    

    What they have in NavLink:

          <Tag {...attributes} ref={innerRef} onClick={this.onClick} className={classes} />
    

    Where {...attributes} will be any other property other than: className, cssModule, active, tag, innerRef, because they are destructed from props.

    So, The reason they did that.

    1. They needed/provided onClick property for the Link component.
    2. They have there own standard to styling stuff className={classes}

    And, one of the most important things in React is it's Component's Re-usability, meaning, DRY principle is applied in this matter, because, Imagine you don't have the NavLink Component and you want to add a onClick prop for the Link component whenever it's needed, then you'll have to carry this around wherever you go:

      onClick(e) {
        if (this.props.disabled) {
          e.preventDefault();
          return;
        }
    
        if (this.props.href === '#') {
          e.preventDefault();
        }
    
        if (this.props.onClick) {
          this.props.onClick(e);
        }
      }
    

    Shortening that: it's all for the sake of DRY Principle