Creating a styled component inside a component function In one of my React components, I want to use props when creating a styled-component to determine which tag to use. Specifically I am looking for what's in props.headingLevel to decide which heading level to create. E.g. h1 or h2.

All of the styled-components examples show components being created outside of the React component class or function, however I have only got this working by creating the styled-component inside the function when props is available. I know you can use props inside of the styled-component via the props passed to the styled-component itself within the React function but at this point it's too late.

So my question is twofold. Is it acceptable to create styled-components inside React components functions? And, is there a better way to manage dynamic tags, e.g. creating a styled-component tag based on context or props passed?

Here is my component:

// Modules
import React from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';

// Data
import styleData from '../../../data/styles';

const SupplementaryTitle = styled.span`
    display: block;
    text-align: right;
`

const Title = (props) =&gt; {
    const HeadingLevel = props.headingLevel ? props.headingLevel : 'h2';
    const StyledHeading = styled(HeadingLevel)`
        margin: 0;
        font-weight: ${styleData['typography_settings']['title'][props.typographySize]['weight']};
        font-size: ${styleData['typography_settings']['title'][props.typographySize]['size']};
        font-family: ${styleData['typography_settings']['title'][props.typographySize]['font']};
        line-height: ${styleData['typography_settings']['title'][props.typographySize]['line_height']};
    `

    const hasSupplementaryTitle = props.supplementaryTitle;

    if (hasSupplementaryTitle) {
        return (
            &lt;StyledHeading&gt;
                {props.children}
                &lt;SupplementaryTitle&gt;{props.supplementaryTitle}&lt;/SupplementaryTitle&gt;
            &lt;/StyledHeading&gt;
        )
    }

    return (
        &lt;StyledHeading&gt;{props.children}&lt;/StyledHeading&gt;
    )
}

Title.propTypes = {
    children: PropTypes.string.isRequired,
    headingLevel: PropTypes.string,
    typographySize: PropTypes.oneOf([
        'small', 'medium', 'large'
    ]).isRequired,
    supplementaryTitle: PropTypes.string,
}

export default Title;
You generally should not to nest your components. Though when the component is small enough, like a one-liner, it's fine to do so.

In your specific case, you can make use of withComponent method to change the tag name of an existing component:

const Heading = styled.h2`
    margin: 0;
    ...lots of css...
`;

const Title = (props) =&gt; {
    const StyledHeading = Heading.withComponent(props.headingLevel || "h2");
    ...
};


You'd still be defining the StyledHeader inside another component, but most of the code would live outside.

Additionally...


I noticed these long lines:

font-weight: ${styleData['typography_settings']['title'][props.typographySize]['weight']};


Looks like this styleData is some sort of theme. I suggest you look into  built-in theming support of styled components before rolling your own.
The variable hasSupplementaryTitle can be eliminated. It's conventional to perform an existence check by just:

if (props.supplementaryTitle) {