简体   繁体   English

如何使用样式化组件设置嵌套功能组件的样式

[英]How to style a nested functional component using styled components

I have a button with the following props - variant , loading , and disabled .我有一个带有以下道具的按钮 - variantloadingdisabled Plus, I have a button group that accepts buttons as children and gaps them with 20px.另外,我有一个按钮组,它接受按钮作为子按钮并将它们与 20px 间隔。 Something like this:像这样的东西:

按钮规格

Technically speaking, I have two components here.从技术上讲,我这里有两个组件。 A <Button /> and a <ButtonGroup /> .一个<Button />和一个<ButtonGroup /> This would be achievable by writing:这可以通过编写来实现:

const Button = styled.button`
  // css implementation

  :disabled {
    opacity: 0.5;
  }
`;

const ButtonGroup = styled.button`
  // css implementation

  ${Button} + ${Button} {
    margin-inline-start: 20px;
    // PS - I'm aware I could use the `gap` property, but I'm not specifically talking about this example, but in general.
  }
`;

// Usage
<ButtonGroup>
  <Button ... />
  <Button ... />
</ButtonGroup>

The last thing and the main issue here is to implement the loading state of the button.最后一件事也是这里的主要问题是实现按钮的加载 state。 Or in general, adding extra logic to the styled component.或者一般来说,为样式化的组件添加额外的逻辑。 So the "best" way I know of is to create a new functional component and then wrap it inside another styled.因此,我所知道的“最佳”方式是创建一个新的功能组件,然后将其包装在另一个样式中。 Something like this:像这样的东西:

// Button.tsx
const StyledButton = styled.buton`...`;

const Button = (props) => {
  return (
    <StyledButton className={props.className}>
      {props.loading && <LoadingSpinner />}
      {props.children}
    </StyledButton>
  );
}

export default styled(Button)``; // It's needed for for nested styling.

...

// ButtonGroup.tsx
const ButtonGroup = styled.button`
  // css implementation

  ${Button} + ${Button} {
    margin-inline-start: 20px;
    // PS - I'm aware I could use the `gap` property, but I'm not specifically talking about this example, but in general.
  }
`;

It will work, of course, but I'm not sure if it's the best way.当然,它会起作用,但我不确定这是否是最好的方法。 Currently, as you can see, I did it by calling styled component -> function component -> styled component for the simplest component.目前,如您所见,我通过调用 styled component -> function component -> styled component 来实现最简单的组件。 I'm not sure how it will scale with my other components, especially naming these components.我不确定它将如何与我的其他组件一起扩展,尤其是命名这些组件。

So my question is, is there a better, cleaner, simpler way of doing this?所以我的问题是,有没有更好、更清洁、更简单的方法来做到这一点?

I don't see a reason for three components, a pattern that works for me is using dot notation:我没有看到三个组件的原因,对我有用的模式是使用点表示法:

const StyledButton = styled.button``;
const Button = (props) => {
  return (
    <StyledButton className={props.className}>
      {props.loading && <LoadingSpinner />}
      {props.children}
    </StyledButton>
  );
};

Button.Styled = StyledButton;
export default Button;

In this way, you have a pattern where Component.Styled (if available) will always hold the runtime CSS-in-JS object which you can target.这样,您就有了一个模式,其中Component.Styled (如果可用)将始终保存您可以定位的运行时 CSS-in-JS object。

Then in ButtonGroup implementation:然后在ButtonGroup实现中:

import { Button } from "@components";

// You can target the className
const ButtonGroup = styled.div`
  ${Button.Styled} { ... }
`;

// You can apply styles
styled(Button)

// You can use the component
<Button />

// Or extend style etc
<OtherButton as={Button.Styled} .../>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM