样式化组件 + 故事书:当我传递新样式时,SVG 图标不会重新渲染
Posted
技术标签:
【中文标题】样式化组件 + 故事书:当我传递新样式时,SVG 图标不会重新渲染【英文标题】:Styled components + Storybook: SVG Icon is not re-rendering when I pass new styles 【发布时间】: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 更改道具时,没有任何更新。
但是,在生产中,控件什么都不做。
【问题讨论】:
【参考方案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>
);
;
【讨论】:
以上是关于样式化组件 + 故事书:当我传递新样式时,SVG 图标不会重新渲染的主要内容,如果未能解决你的问题,请参考以下文章