Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 639
Alexander Kim Avatar asked Apr 28 '20 19:04

Alexander Kim


People also ask

Can you pass Props to styled component?

Passed propsIf the styled target is a simple element (e.g. styled.div), styled-components passes through any known HTML attribute to the DOM. If it is a custom React component (e.g. styled(MyComponent)), styled-components passes through all props.

What is component prop in material ui?

According to https://mui.com/material-ui/api/button/ , it means "The component used for the root node. Either a string to use a HTML element or a component.".

What are transient props?

Overview: Transient Props allow you to pass boolean value props to styled-components such that they do not render as an element's attributes on the DOM. This prevents the errors and allows for some more complex use of styled-component props.


2 Answers

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

like image 94
Dekel Avatar answered Oct 13 '22 00:10

Dekel


With version 5.1.0, styled-components supports transient props. Transient props are not passed to component (i.e. just used in the styling) and are indicated by starting the prop name with $. This allows for a much simpler way of managing this scenario that no longer requires a wrapper component to remove the extra props (as in Dekel's answer).

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 Text: React.FunctionComponent<TextProps> = styled(Typography)`
  margin-bottom: 10px;
  color: ${({ $textColor }: TextProps) => $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

like image 28
Ryan Cogswell Avatar answered Oct 13 '22 00:10

Ryan Cogswell