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) => {
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 (
<StyledHeading>
{props.children}
<SupplementaryTitle>{props.supplementaryTitle}</SupplementaryTitle>
</StyledHeading>
)
}
return (
<StyledHeading>{props.children}</StyledHeading>
)
}
Title.propTypes = {
children: PropTypes.string.isRequired,
headingLevel: PropTypes.string,
typographySize: PropTypes.oneOf([
'small', 'medium', 'large'
]).isRequired,
supplementaryTitle: PropTypes.string,
}
export default Title;
-
1\$\begingroup\$ If voting this question down, please specify your reasons why so that I can improve the question. \$\endgroup\$James Tudsbury– James Tudsbury2018年04月25日 11:40:36 +00:00Commented Apr 25, 2018 at 11:40
-
1\$\begingroup\$ It's not my DV but this code is incomplete and there isn't really much to review... \$\endgroup\$t3chb0t– t3chb0t2018年04月25日 12:43:33 +00:00Commented Apr 25, 2018 at 12:43
-
1\$\begingroup\$ Updated to include full component code rather than snippet. Thanks for the input \$\endgroup\$James Tudsbury– James Tudsbury2018年04月25日 15:49:34 +00:00Commented Apr 25, 2018 at 15:49
1 Answer 1
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) => {
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) {
-
\$\begingroup\$ This is great feedback! Thanks. Definitely going to make use of
withComponent
and I don't know why I made the decision to havehasSupplementaryTitle
. Over explaining myself in the code. I am going to look into theming more to see if it fits what I'm trying to do,styleData
is basically a big object with all of my style values and the context they apply to, derived from the idea of design tokens. \$\endgroup\$James Tudsbury– James Tudsbury2018年04月27日 07:55:08 +00:00Commented Apr 27, 2018 at 7:55