John Goofy
John Goofy

Reputation: 998

Styled-Components & React: how to avoid cluttering?

I've recently started to use Styled Components together with React, and I am unsure if I am handling a particular case right which keeps reoccuring.

Let's say I have a very simple component like a Label which needs only a very styles and some given content. I would now handle this is follows:

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>;

I find it circumstantial to define base components like Impl first, only for the styles, and then then another component which takes the props and uses that styled component.

Is there a shorter way to do both in only one component? I was hoping for something like ...

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

... but that doesn't seem to work.

Upvotes: 1

Views: 264

Answers (1)

cbr
cbr

Reputation: 13652

One way you could do this is to use the styled factory and just inline your component - though this kind of inverses the relation in the sense that you're not using a styled.span, but rather just styling your own component via the className generated by styled-components. This also means that you need to include className? in your props' type, or use an utility type to add it in.

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" />
    </>
  );
}

You might also prefer this:

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

or with a utility type:

type SCP<T> = T & { 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;
`;

Upvotes: 3

Related Questions