【问题标题】:Styled components + Storybook: SVG Icon is not re-rendering when I pass new styles样式化组件 + 故事书:当我传递新样式时,SVG 图标不会重新渲染
【发布时间】:2021-07-21 06:20:26
【问题描述】:

我正在尝试创建一个 SvgIcon 组件,我通过道具将 SVG 传递给该组件。

由于 React 处理 SVG 的方式,当它们作为 ReactComponents 导入时(例如import { ReactComponent as ArrowIcon } from "icons/arrow.svg"),我必须以动态方式定义我的组件。

这是我目前所拥有的:

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

`;

const SvgIcon = ({ stroke, fill, size, icon }) => {
  const theme = useTheme();

  const StyledIcon = styleSvgIcon({ theme, stroke, fill, size, icon });
  console.log('styledddddddddd', StyledIcon);  // prints the styled component with the new styles, but on the page nothing changes
  return <StyledIcon />;
};

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 React from 'react';
import SvgIcon from './SvgIcon';
import * as all_icons from '../icons';

import { SVG_ICON_SIZES, SVG_ICON_COLORS } from '../constants/variants';

export default {
  title: 'media/SvgIcon',
  component: SvgIcon,
  argTypes: {
    size: {
      type: 'select',
      options: Object.values(SVG_ICON_SIZES),
      defaultValue: SVG_ICON_SIZES.SMALL,
    },
    stroke: {
      type: 'select',
      options: Object.values(SVG_ICON_COLORS),
      defaultValue: SVG_ICON_COLORS.PRIMARY,
    },
    fill: {
      type: 'select',
      options: Object.values(SVG_ICON_COLORS),
      defaultValue: SVG_ICON_COLORS.PRIMARY,
    },
  },
};

const Template = (args) => {
  const icons = Object.values(all_icons);
  // return icons.map((SvgComponent, i) => (
  return icons
    .slice(0, 2)
    .map((SvgComponent, i) => (
      <SvgIcon key={i} {...args} icon={SvgComponent} />
    ));
};

export const Small = Template.bind({});
Small.args = {
  size: SVG_ICON_SIZES.SMALL,
};

export const Medium = Template.bind({});
Medium.args = {
  size: SVG_ICON_SIZES.MEDIUM,
};

export const Large = Template.bind({});
Large.args = {
  size: SVG_ICON_SIZES.LARGE,
};

export const XL = Template.bind({});
XL.args = {
  size: SVG_ICON_SIZES.XL,
};

这在本地运行良好,但是当我部署我的应用并尝试通过 Storybook 更改道具时,没有任何更新。

但是,在生产中,控件什么都不做。

【问题讨论】:

    标签: reactjs styled-components storybook


    【解决方案1】:

    我想通了!!!

    所以因为我只是设置样式而不使用这样的道具:

    size: ${calculate(size)};

    styled-components 以某种方式知道,因此不会将侦听器添加到更新的道具。所以我的StyledIcon 只是成为一个静态组件,在传入新样式时不会更新,因为它们只是一成不变的。

    相反,将它们作为 props 传递并通过 props 访问它们会添加这些侦听器

    const SvgIcon = ({ stroke, fill, size, icon: Icon }) => {
      const StyledIcon = styled(Icon).attrs({
        viewBox: `0 0 24 24`,
      })`
        path {
          stroke: ${({ stroke, theme }) =>
            calculateColor({ color: stroke, theme })};
          fill: ${({ fill, theme }) => calculateColor({ color: fill, theme })};
        }
        height: ${({ size }) => calculateSize(size)};
        width: ${({ size }) => calculateSize(size)};
      `;
    
      return (
        <div>
          <StyledIcon size={size} fill={fill} stroke={stroke} />,{size},{fill},
          {stroke}
          <StyledArrowUpIcon stroke={stroke} size={size} fill={fill} />
        </div>
      );
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-17
      • 2020-02-26
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多