首页 > 解决方案 > styled-components:组件...已动态创建

问题描述

我正在尝试创建一个自定义 SVG 图标组件。众所周知,SVG 在 react 中的处理方式与普通 HTML 元素略有不同。

因此,我不能像往常一样在渲染函数之外定义它。这就是我现在所拥有的:

SvgIcon.js

const SvgIcon = ({ stroke, fill, size, icon: Icon, className }) => {
  const StyledIcon = styled(Icon).attrs({
    viewBox: `0 0 24 24`,
  })`
    path {
      ${({ custom_stroke, theme }) =>
        custom_stroke &&
        `stroke: ${calculateColor({ color: custom_stroke, theme })};`}
      ${({ custom_fill, theme }) =>
        custom_fill &&
        `fill: ${calculateColor({ color: custom_fill, theme })};`}
    }
    height: ${({ size }) => calculateSize({ size })};
    width: ${({ size }) => calculateSize({ size })};
  `;

  return (
    <StyledIcon
      className={className}
      size={size}
      custom_fill={fill}
      custom_stroke={stroke}
    />
  );
};

SvgIcon.propTypes = {
  stroke: PropTypes.oneOf(Object.values(SVG_ICON_COLORS)),
  fill: PropTypes.oneOf(Object.values(SVG_ICON_COLORS)),
  size: PropTypes.oneOf(Object.values(SVG_ICON_SIZES)),
  icon: PropTypes.elementType.isRequired,
};

export default SvgIcon;

这是这样使用的:

import { ReactComponent as ArrowUpIcon } from '../ui/icons/arrow-up.svg';
<SvgIcon icon={ArrowUpIcon} size={"small"} stroke={"blue"} fill={"green"} />

但是,在控制台中,styled-components 抱怨:

The component SvgIcon__StyledIcon with the id of "SvgIcon__StyledIcon-sc-77lkhb-0" has been created dynamically.
You may see this warning because you've called styled inside another component.
To resolve this only create new StyledComponents outside of any render method and function component.

如何在没有警告的情况下制作自定义 SvgIcon 组件?

标签: reactjsstyled-components

解决方案


我最终只是将 SVG 包装在一个 div 中并通过 CSS 访问样式

const IconWrapper = styled.div`
  display: inline-block;
  svg {
    path {
      ${({ custom_stroke, theme }) =>
        custom_stroke &&
        `stroke: ${calculateColor({ color: custom_stroke, theme })};`}
      ${({ custom_fill, theme }) =>
        custom_fill &&
        `fill: ${calculateColor({ color: custom_fill, theme })};`}
    }
    height: ${({ size }) => calculateSize({ size })};
    width: ${({ size }) => calculateSize({ size })};
  }
`;

const SvgIcon = ({ stroke, fill, size, icon: Icon }) => (
  <IconWrapper size={size} custom_fill={fill} custom_stroke={stroke}>
    <Icon viewBox="0 0 24 24" />
  </IconWrapper>
);

SvgIcon.propTypes = {
  stroke: PropTypes.oneOf(Object.values(SVG_ICON_COLORS)),
  fill: PropTypes.oneOf(Object.values(SVG_ICON_COLORS)),
  size: PropTypes.oneOf(Object.values(SVG_ICON_SIZES)),
  icon: PropTypes.elementType.isRequired,
};

export default SvgIcon;


推荐阅读