Search code examples
typescriptmaterial-uiemotion

How to prevent passing props to inner styled component


I'm trying to make a composition on top of the material UI components changing only the style via given props.

import { Typography } from "@mui/material";
import { styled } from "@mui/system";

type MyTypographyExtraProps = { isEven?: boolean };

export const MyTypography = styled(Typography)<MyTypographyExtraProps>(
  ({ theme, isEven }) => `
   color: ${theme.palette.common.black};

   ::after {
      content: "";
      display: inline-block;
      height: ${theme.spacing(2)};
      width: ${theme.spacing(2)};
      border-radius: ${theme.spacing(2)};
      background-color: ${theme.palette[isEven ? "success" : "error"].main};
   }
  `,
);

The styled function passed my isEven props to the Material Typography component, and Typography passes it to DOM, so I get the warning

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

How can I omit the type before getting passed to the typography element?

I can make another component and eliminate the props in that layer, but I'm curious to know is there any way to do it without an extra component.


Solution

  • Material docs suggest a function to eliminate props from being passed.

    shouldForwardProp: Say what props must be passed down to styled given components.

    export const MyTypography = styled(MuiTypography, {
      shouldForwardProp: prop => prop !== "isEven", // ⭐
    })<MyTypographyExtraProps>(
      ({ theme, isEven }) => `
       color: ${theme.palette.common.black};
    
       ::after {
          content: "";
          display: inline-block;
          height: ${theme.spacing(2)};
          width: ${theme.spacing(2)};
          border-radius: ${theme.spacing(2)};
          background-color: ${theme.palette[isEven ? "success" : "error"].main};
       }
      `,
    );
    

    NOTE: shouldForwardProps and skipSx props are not perfectly aligned if your you want to prevent sx and other props simultaneously.
    For more info see this github issue