Search code examples
javascriptreactjstypescriptmaterial-uistyled-components

React does not recognize the prop passed to a styled-component within Material UI


Styled-component:

import { Typography } from '@material-ui/core';

const Text = styled(Typography)<TextProps>`
  margin-bottom: 10px;
  color: ${({ textColor }) => textColor ?? textColor};
  font-size: ${({ textSize }) => (textSize ? textSize + 'px' : '16px')};
`;

Usage inside a component:

<GlobalStyled.Text textColor="green" textSize="20">test</GlobalStyled.Text>

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

Props are passed to a Typography component itself, not just for styled-component, how to workaround this?

UPDATE

Styled components released 5.1.0: https://github.com/styled-components/styled-components/releases/tag/v5.1.0

There's new transient props now, that solves this problem with props filtering. You can use $propsName, a dollar sign before your props name and it will be passed to a Styled-component ONLY!


Solution

  • You will need to get the props that you don't want, strip them, and pass the rest of the inside:

    const Text = styled( ({textColor, textSize, ...rest}) => <Typography {...rest}/>)<TextProps>`
      margin-bottom: 10px;
      color: ${({ textColor }) => textColor ?? textColor};
      font-size: ${({ textSize }) => (textSize ? textSize + "px" : "16px")};
    `;
    

    Here is a working example (without the TextProps type, but it should work): https://codesandbox.io/s/mui-styled-component-removed-props-rfdjx?file=/src/App.js

    Here is a working example using Typescript:

    import * as React from "react";
    
    import Typography, {TypographyProps} from '@material-ui/core/Typography';
    import {StylesProvider} from '@material-ui/core/styles';
    import styled from 'styled-components';
    
    interface TextProps extends TypographyProps {
      textColor: string,
      textSize: number
    }
    
    const TypographyWrapper = React.forwardRef<HTMLSpanElement, TextProps>(
      function TypographyWrapper({textColor, textSize, ...other}: TextProps, ref) {
        return <Typography {...other} ref={ref}/>
      }
    );
    const Text = styled(TypographyWrapper)<TextProps>`
      margin-bottom: 10px;
      color: ${({ textColor }: TextProps) => textColor ?? textColor};
      font-size: ${({ textSize }: TextProps) => (textSize ? textSize + 'px' : '16px')};
    `;
    
    export default function App() {
      return <StylesProvider injectFirst>
        <Text textColor="green">Hello World!</Text>
        <Text textColor="red" textSize={30}>Hello World!</Text>
      </StylesProvider>;
    }
    

    Edit Remove props that are only for styled-components