Extending Styles with Styled-Components Not Working

Extending styles with styled-components not working

As stated in documentation:

The styled method works perfectly on all of your own or any
third-party components, as long as they attach the passed className
prop to a DOM element.

Example

// This could be react-router-dom's Link for example, or any custom component
const Link = ({ className, children }) => (
<a className={className}>
{children}
</a>
);

const StyledLink = styled(Link)`
color: palevioletred;
font-weight: bold;
`;

render(
<div>
<Link>Unstyled, boring Link</Link>
<br />
<StyledLink>Styled, exciting Link</StyledLink>
</div>
);

Ref: https://www.styled-components.com/docs/basics#styling-any-component

Styled-components: Styles are not applied when trying to style already styled component

First, move the styled component outside of function scope or your style will reset on every render and you will get heavy performance issues.

Secondly, in order to apply styles, you need to pass className property.

See Styling normal React components

If you use the styled(MyComponent) notation and MyComponent does not render the passed-in className prop, then no styles will be applied.

const Container = styled.div`
display: flex;
align-items: center;
height: 36px;
& > div:not(:last-child) {
margin-right: 5px;
}
`;
const LanguageChooser = ({ className }) => {
return (
<Container className={className}>
<Flag {...languages.pl} />
<Flag {...languages.en} />
</Container>
);
};

const Button = styled.div`
cursor: pointer;
font-size: 24px;
transition: 0.2s all;
&:hover {
font-size: 36px;
}
`;

const Flag = ({ flag, language }) => {
const { i18n } = useTranslation();

return <Button onClick={() => i18n.changeLanguage(language)}>{flag}</Button>;
};

styled-components not applying style to custom functional react component

From the docs:

The styled method works perfectly on all of your own or any
third-party components as well, as long as they pass the className
prop to their rendered sub-components, which should pass it too, and
so on. Ultimately, the className must be passed down the line to an
actual DOM node for the styling to take any effect.

For example, your component would become:

const Div = ({ className }) => (<div className={className}>test</div>)
const StyledDiv = styled(Div)`
color: green;
`;

Modified example:

const styled = styled.default
const Div = ({ className }) => (<div className={className}>test</div>)
const StyledDiv = styled(Div)`
color: green;
font-size: larger;
`;
const App = () => {
return(<StyledDiv>Test</StyledDiv>)
}

ReactDOM.render(<App />, document.querySelector('.app'))
<script src="//unpkg.com/react@16.5.2/umd/react.development.js"></script>
<script src="//unpkg.com/react-dom@16.5.2/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/styled-components/3.4.9/styled-components.min.js"></script>
<div class="app"></div>

styled-components: Extend existing component with additional prop for styling

This is exactly what transient props are for.

All you need to do is prefix the prop with a $ and styled-components won't pass the prop to the underlying DOM element.

// Note the $ prefix in the prop name             br>const StyledToggleButton = styled(ToggleButton)<{ $hasMargin?: boolean }>`
&& {
color: red;

// Just use the prop as normal
${(props) =>
props.$hasMargin &&
css`
margin: 10px;
`}
}
`;

<StyledToggleButton
value={""}
size={"small"}
{/* Assign the prop as normal */}
$hasMargin={true}
>
click
</StyledToggleButton>;

Here's your updated Codesandbox link with that error gone.

Extending regular React components with styled-components

I don't really know where the confusion lies, you can pass any React component to the styled Higher Order Component.

The issue you have is that you aren't trying to style the BoxFunctional or BoxClass components, but rather you are trying to style the JSX they render. You just need to proxy the className prop through to what each renders.

Styling any Component

The styled method works perfectly on all of your own or any
third-party component, as long as they attach the passed className
prop to a DOM element.

const BoxFunctional = (props) => (
<div className={props.className}>{props.children}</div>
);

class BoxClass extends Component {
render() {
return <div className={this.props.className}>{this.props.children}</div>;
}
}

Demo

Edit extending-regular-react-components-with-styled-components

Sample Image

How to extend component style in styled-components

Since ElipseDetails is not a styled component, but calls to a styled one, you can do something like:

function ElipseDetail({ text, children }: Props): ReactElement {
return (
<Container>
<Text>{text}</Text>
{children}
</Container>
);
}

ElipseDetail.Styled = Container;

export default ElipseDetail

And then, in a different component, you can change it like so:


const StyledElipseDetail = styled(ElipseDetail.Styled)`
${Text} {
//
}
`;

...

return <StyledElipseDetailed>...</StyledElipseDetail>

PS - I have taken this approach from an older question of mine which I found quite useful.



Related Topics



Leave a reply



Submit