reactjstypescriptbabeljsstyled-components

Avoid passing down props using Styled Components and Typescript


I have the following Styled Component in a React app that works as expected:

const BaseButton = styled(Button)<{ borderColor: string }>`
  border-color: ${({ borderColor }): string => borderColor};
`;

However it generates this warning message in the console:

React does not recognize the borderColor prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase bordercolor instead. If you accidentally passed it from a parent component, remove it from the DOM element.

In order to avoid this, I've tried to implement the solution proposed in the documentation

Documentation example:

import styled from 'styled-components'
import Header, { Props as HeaderProps } from './Header'

const Title =
  styled <
  { isActive: boolean } >
  (({ isActive, ...rest }) => <Header {...rest} />)`
  color: ${props => (
  props.isActive ? props.theme.primaryColor : props.theme.secondaryColor
)}
`

My original code rewritten following the example:

const BaseButton = styled <
{ borderColor: string } >
(({ borderColor, ...rest }) => <Button {...rest} />)`
  border-color: ${({ borderColor }): string => borderColor};
`;

But I get the following error message:

Parsing error: '>' expected

The error refers to <Button {rest...} />

This is my .babelrc config in case something is amiss:

{
  "presets": ["@babel/env", "@babel/typescript", "@babel/preset-react"],
  "plugins": [
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/transform-runtime",
    "@babel/plugin-transform-modules-commonjs"
  ]
}

Solution

  • Use Transient props

    TL;DR just prefix your attriibute with $ sign. example $borderColor, $black, $any, $attribute.

    If you want to prevent props meant to be consumed by styled components from being passed to the underlying React node or rendered to the DOM element, you can prefix the prop name with a dollar sign ($), turning it into a transient prop.

    // typescript example
    const BaseButton = styled(Button)<{ $borderColor: string }>`
        border-color: ${({ $borderColor }): string => $borderColor};
    `;
    
    
    // js
    const BaseButton = styled(Button)`
        border-color: ${({$borderColor}) => $borderColor}
    `;
    
    // usage
    <BaseButton $borderColor="red">Button</BaseButton>
    
    

    2nd method

    Checkout shouldForwardProp

    const Comp = styled('div').withConfig({
      shouldForwardProp: (prop, defaultValidatorFn) =>
          !['hidden'].includes(prop)
          && defaultValidatorFn(prop),
    }).attrs({ className: 'foo' })`
      color: red;
      &.foo {
        text-decoration: underline;
      }
    `;
    
    render(
      <Comp hidden draggable="true">
        Drag Me!
      </Comp>
    );