Styled Component dynamic tag name
Asked Answered
E

3

10

I want to make a dynamic component. (the dynamic TAG will be a styled component -> emotion)

const Dynamic = ({ tag: Tag, children, ...rest }) =>
   <Tag {...rest}>
      { children }
   </Tag>

The component will be a styled component like:

const Column = styled(div)({ color: 'red' })
const Row = styled(span)({ color: 'yellow' })

This looks all nice, and working properly, BUUUUUT:

When I try use a DynamicComponent inside another DynamicComponent:

<DynamicComponent tag={Row}>
   {
      mapOver.map(item=>
         <DynamicComponent tag={Column}/>
      )
   }
</DynamicComponent>

then for some reason the Dynamic children will use the Dynamic Parent's style.

Is there anything I missing?

P.S.:

If instead of using dynamic styles, I do something like this:

<Row>
   <Column/>
</Row>

then the styles, classNames, styled tags, are applied properly.

To make it a little more clear:

enter image description here

As you can see the DynamicComponent's will use the parent's styles, classNames, styled tags... (NOT THE BEHAVIOUR I WOULD EXPECT)

Embrasure answered 30/8, 2018 at 9:21 Comment(0)
P
0

There is a misunderstanding in the usage of styled-components as a tag is intended as HTML tag (input, div and so on). The best way is to define a StyledRow and a StyledColumn separately and use them with appropriate names. This will help also to make your code more readable.

Peerless answered 30/8, 2018 at 9:52 Comment(1)
Make sense, I just wanted to check how others are see this kind of thing. Thanks mate! :)Embrasure
E
25

Below example creating a dynamic tag name for a styled-component:

// All headings use the same styled-component "Heading" function
const StyledHeading = styled.div`
    font-size: ${({level}) => 4/level }em; // <- dynamic font size
    font-weight: 300;
    margin: 0;
`

// the trick here is the "as={...}" to create dynamic tag name
const Heading = ({level = 1, children}) => 
    <StyledHeading as={`h${level}`} level={level}>
        {children}
    </StyledHeading>


ReactDOM.render([
    <Heading>Hello, world!</Heading>,
    <Heading level={2}>Title 2</Heading>,
    <Heading level={3}>Title 3</Heading>
  ] ,document.body
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/styled-components.min.js"></script>

Reference:

Entablement answered 8/7, 2019 at 12:1 Comment(0)
V
1

You can use as props of styled component. For example:

<Badge as="div" />

or <Badge as="span" />

Venenose answered 25/5, 2023 at 7:36 Comment(0)
P
0

There is a misunderstanding in the usage of styled-components as a tag is intended as HTML tag (input, div and so on). The best way is to define a StyledRow and a StyledColumn separately and use them with appropriate names. This will help also to make your code more readable.

Peerless answered 30/8, 2018 at 9:52 Comment(1)
Make sense, I just wanted to check how others are see this kind of thing. Thanks mate! :)Embrasure

© 2022 - 2024 — McMap. All rights reserved.