Styled-Components

#reactjs #styled-components

#reactjs #styled-components

Вопрос:

Недавно я начал использовать стилизованные компоненты вместе с React, и я не уверен, правильно ли я справляюсь с конкретным случаем, который продолжает повторяться.

Допустим, у меня есть очень простой компонент, такой как a Label , который нуждается только в очень стилях и некотором заданном контенте. Теперь я бы справился с этим следующим образом:

 import React from "react";
import styled from "styled-components";

export type Props = {...};

export const Impl = styled.span`
  display: inline-block;
  padding: 0 4px;
  ...
`;

export const Label: React.FC<Props> = ({ text }) => <Impl>{ text }</Impl>;
 

Я нахожу целесообразным определить базовые компоненты, такие как Impl first, только для стилей, а затем другой компонент, который берет реквизит и использует этот стилизованный компонент.

Есть ли более короткий способ сделать и то, и другое только в одном компоненте? Я надеялся на что — то вроде …

 export const Label = styled.span<Props>=`
  ...styles...
`({ label }) = { label };
 

… но это, похоже, не работает.

Комментарии:

1. Вы могли бы использовать .attrs() для выбора children реквизита, но посмотрите, сможете ли вы выяснить, как применять типы: const Label = styled.span.attrs({ children: (props) => props.text })`display: inline-block;`;

2. Похоже, что последние стилизованные компоненты .attrs используются в функции: styled.span.attrs((props: Props) => ({ children: props.text }))`display: inline-block;`

Ответ №1:

Один из способов, которым вы могли бы это сделать, — использовать styled factory и просто встроить свой компонент — хотя это инвертирует отношение в том смысле, что вы не используете a styled.span , а просто стилизуете свой собственный компонент с помощью className generated by styled-components . Это также означает, что вам нужно включить className? в тип вашего реквизита или использовать тип утилиты, чтобы добавить его.

 type Props = {
  text: string;
  className?: string;
};

const Label = styled(({ text, className }: Props) => (
  <span className={className}>{text}</span>
))`
  display: inline-block;
  padding: 0 4px;
  color: red;
`;

export default function App() {
  return (
    <>
      <Label text="foo" />
    </>
  );
}
 

Вы также можете предпочесть это:

 const Label = styled(({ text, ...props }: Props) => (
  <span {...props}>{text}</span>
))`
  display: inline-block;
  padding: 0 4px;
  color: red;
`;
 

или с типом утилиты:

 type SCP<T> = T amp; { className?: string };

type Props = {
  text: string;
};

const Label = styled(({ text, ...props }: SCP<Props>) => (
  <span {...props}>{text}</span>
))`
  display: inline-block;
  padding: 0 4px;
  color: red;
`;
 

Комментарии:

1. Вау. Спасибо за ваше время и поддержку, @cbr, я не знал о заводской функции; это выглядит как довольно крутое решение!

2. @JohnGoofy Вы также можете использовать его с любым другим компонентом, который передается className дальше 🙂 например styled(Component)