reactjs 如何将props传递给样式化组件而不将其转换为 transient props?

kqlmhetl  于 2023-05-17  发布在  React
关注(0)|答案(2)|浏览(118)

我已经创建了一个Text组件,它接收了几个props。这些props被传递到样式化组件,在那里应用样式。我不想把props传递给DOM,我只想在样式化的组件中访问它们。
将props转换为transient props是可行的,但它会创建重复的代码,我认为这会使整个组件变得不必要的大。
我想知道,如何传递一些 prop 到我的风格组件,而不传递给DOM,而不必重新定义每个 prop 。我试过使用shouldForwardProps,但我不能让它与Typescript一起工作。

type Props = {
  children: React.ReactNode;
  size: number;
  height: number;
  color: string;
};

const StyledText = styled.p<{ $color: string; $size: number; $height: number }>`
  color: ${({ $color }) => $color};
  font-size: ${({ $size }) => `${$size}px;`};
  line-height: ${({ $height }) => `${$height}px;`};
  ...
`;

const Text: React.FC<Props & React.HTMLAttributes<HTMLParagraphElement>> = ({ children, size, height, color, ...rest }) => {
  return (
    <StyledText $size={size} $height={height} $color={color} {...rest}>
      {children}
    </StyledText>
  );
};
ou6hu8tu

ou6hu8tu1#

这里是一个使用shouldForwardProps的解决方案,正如你所建议的,我相信这是你所要求的。我曾尝试将customAttributeNames绑定到Props,但我已经放弃了。

const customAttributeNames = ["size", "height", "color"] as const;

type TCustomAttribute = typeof customAttributeNames[number];

type Props = React.HTMLAttributes<HTMLParagraphElement> & {
  children: React.ReactNode;
  size: number;
  height: number;
  color: string;
};

const StyledTextWithoutDomAttributes = styled.p.withConfig({
  shouldForwardProp: (prop) =>
    !(customAttributeNames as readonly string[]).includes(prop)
})<Pick<Props, TCustomAttribute>>`
  color: ${({ color }) => color};
  font-size: ${({ size }) => `${size}px;`};
  line-height: ${({ height }) => `${height}px;`};
`;

const StyledTextWithDomAttributes = styled.p<Pick<Props, TCustomAttribute>>`
  color: ${({ color }) => color};
  font-size: ${({ size }) => `${size}px;`};
  line-height: ${({ height }) => `${height}px;`};
`;

const Text: React.FC<Props> = ({ children, size, height, color, ...rest }) => {
  return (
    <>
      <StyledTextWithDomAttributes
        size={size}
        height={height}
        color={color}
        {...rest}
      >
        {children}
      </StyledTextWithDomAttributes>
      <StyledTextWithoutDomAttributes
        size={size}
        height={height}
        color={color}
        {...rest}
      >
        {children}
      </StyledTextWithoutDomAttributes>
    </>
  );
};

这是一个sandbox,所以你可以看到它的工作。

qoefvg9y

qoefvg9y2#

您需要的是拥有一个默认的StyledText组件,然后使用styled函数覆盖该组件

const StyledText = styled.p`
  color: #000;
  font-size: 1rem;
  line-height: 130%;
`;

然后像这样覆盖它

const StyledTextLarge = styled(StyledText)`
  color: #333333;
  font-size: 1.2rem;
  line-height: 140%;
`;

通常在设计系统中,您定义文本/排版的不同变体。它是有限的(即:标题、副标题、文本)。因此,最好是有不同的组件,这样比影响最终用户传递变量,风险不符合您想象的设计

相关问题