gajus / babel-plugin-react-css-modules

Transforms styleName to className using compile time CSS module resolution.
Other
2.05k stars 162 forks source link

Compiled className get's overwritten by className from the props #268

Open bohdanbirdie opened 4 years ago

bohdanbirdie commented 4 years ago

Having two components, NavIconLink and AnchorDefault I pass styleName to the AnchorDefault, but also there might be a className from the props spread that will be passed as well. In this case of className is passed - whatever was transformed from styleName to className get's overwritten by passed className from the spread.


import React from 'react';
import PropTypes from 'prop-types';

import {
    AnchorDefault,
    Icon,
} from '../../elements';

import styles from './NavIconLink.scss';

export const NavIconLink = ({
    label,
    icon,
    ...props
}) => (
    <AnchorDefault
        styleName="a-navicon-link"
        activeClassName={styles['a-navicon-link--active']}
        {...props}
    >
        <span className="u-visible-sml">
            {label}
        </span>
        <span className="u-block-md">
            <Icon
                className="a-svg-medium"
                icon={icon}
            />
        </span>
    </AnchorDefault>
);

NavIconLink.propTypes = {
    label: PropTypes.string,
    icon: PropTypes.string,
};

Compiled part

var NavIconLink = function NavIconLink(_ref) {
  var label = _ref.label,
      icon = _ref.icon,
      props = _objectWithoutProperties(_ref, ["label", "icon"]);

  return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_elements__WEBPACK_IMPORTED_MODULE_2__[/* AnchorDefault */ "b"], _extends({
    className: "a-navicon-link___36tEr" + (" " + (props ? props.className || "" : "")),
    activeClassName: _NavIconLink_scss__WEBPACK_IMPORTED_MODULE_3___default.a['a-navicon-link--active']
  }, props), _jsx("span", {
    className: "u-visible-sml"
  }, void 0, label), _jsx("span", {
    className: "u-block-md"
  }, void 0, _jsx(_elements__WEBPACK_IMPORTED_MODULE_2__[/* Icon */ "s"], {
    className: "a-svg-medium",
    icon: icon
  })));
};
import React from 'react';
import PropTypes from 'prop-types';
import { NavLink } from 'react-router-dom';

export const AnchorDefault = ({
    label,
    onClick,
    children,
    disabled,
    className,
    openNewTab,
    ...other
}) => {
    const LinkComponent = other.to
        ? NavLink
        : other.href ? 'a' : 'button';

    return (
        <LinkComponent
            onClick={onClick}
            className={className}
            disabled={disabled}
            {...openNewTab && { target: '_blank' }}
            {...openNewTab && { rel: 'noopener noreferrer' }}
            {...other}
        >
            {children || label}
        </LinkComponent>
    );
};

AnchorDefault.propTypes = {
    children: PropTypes.any,
    label: PropTypes.string,
    disabled: PropTypes.bool,
    className: PropTypes.string,
    href: PropTypes.string,
    onClick: PropTypes.func,
    openNewTab: PropTypes.bool,
};

export default AnchorDefault;

The current workaround is to manually write className prop and set it.

export const NavIconLink = ({
    label,
    icon,
    className,
    ...props
}) => (
    <AnchorDefault
        styleName="a-navicon-link"
        className={className} // <--- here
        activeClassName={styles['a-navicon-link--active']}
        {...props}
    >
        <span className="u-visible-sml">
            {label}
        </span>
        <span className="u-block-md">
            <Icon
                className="a-svg-medium"
                icon={icon}
            />
        </span>
    </AnchorDefault>
);
var NavIconLink = function NavIconLink(_ref) {
  var label = _ref.label,
      icon = _ref.icon,
      className = _ref.className,
      props = _objectWithoutProperties(_ref, ["label", "icon", "className"]);

  return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_elements__WEBPACK_IMPORTED_MODULE_2__[/* AnchorDefault */ "b"], _extends({
    className: (className ? className + " " : "") + "a-navicon-link___36tEr" + (" " + (props ? props.className || "" : "")),
    activeClassName: _NavIconLink_scss__WEBPACK_IMPORTED_MODULE_3___default.a['a-navicon-link--active']
  }, props), _jsx("span", {
    className: "u-visible-sml"
  }, void 0, label), _jsx("span", {
    className: "u-block-md"
  }, void 0, _jsx(_elements__WEBPACK_IMPORTED_MODULE_2__[/* Icon */ "s"], {
    className: "a-svg-medium",
    icon: icon
  })));
};
bohdanbirdie commented 4 years ago

seems like this is because of props = _objectWithoutProperties(_ref, ["label", "icon", "className"]); having className included @gajus any thoughts on that? I tried to modify plugin code, but without success so far

tyler-dot-earth commented 4 years ago

@bohdanbirdie Try putting styleName after the props spread.

bohdanbirdie commented 4 years ago

@tsnieman, unfortunately, it won't add className to the excluded props