Why Is styled-components "styled" Wrapper Not Working With Existing React Component?

When applying styling to an existing (own or third party) React component using styled-components' styled(MyComponent) notation, it is important that the className prop (or style prop, if you're using react-native) is attached to a DOM element in that React component. If that is not the case, then the styling won't be applied.

To demonstrate this, consider for example the following where no styling would be applied to the PrimaryButton component as the className prop is not added to a DOM element in the Button component (which it extends):

// Button.jsx
const Button = ({ children }) => (
  <button>{children}</button>
);
// PrimaryButton.jsx
import styled from 'styled-components';
import Button from 'Button';

const PrimaryButton = styled(Button)`
  color: white;
  background-color: blue;
`;

To avoid this issue, make sure the React component you're using with the styled() wrapper attaches the passed-in className prop (or style prop, if you're using react-native) to a DOM node:

// ...
const Button = ({ className, children }) => (
  <button className={className}>
    {children}
  </button>
);

For a complete example, or to learn more, read the post about extending styles of React component using styled-components.

If you're using TypeScript, it may complain about the className (or style) prop as it doesn't know that it's passed by the styled-components wrapper. In that case, you can mark the prop as optional in your Props interface:

interface ButtonProps {
  className?: string;
}

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.