theJuls
theJuls

Reputation: 7470

Getting warning from props passed in MUI styled components related to React not recognizing it

I have a styled component that needs to receive props to decide how it should be styled. Looks something like this:

const StyledTypography = styled(Typography)(
  ({ myColor = "black", isLarge = false }) => ({
    "&&": {
      fontSize: isLarge ? 30 : 16,
      border: `1px solid ${myColor}`,
      margin: 10,
      color: myColor
    }
  })
);

Unfortunately isLarge causes the following warning:

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

(Same with myColor)

In another thread, I was told that all that needs to be done is to use shouldForwardProp as a function returning a boolean in the second parameter to decide what props should be passed in tot the DOM DOM:

const StyledTypography = styled(Typography, { shouldForwardProp: () => false })(
 ...
);

Unfortunately this doesn't work.

Is there anyway to do this?

Here is a working sample app with the warnings and everything: https://codesandbox.io/s/crimson-fast-qll47?file=/src/App.js

Upvotes: 14

Views: 10575

Answers (4)

ornic
ornic

Reputation: 382

There is a more-or-less universal way of using shouldForwardProp based on styled-components behaviour: we name our internal props starting with $ and they're not being forwarded to the component being styled (div in my example).

export const SidebarList = styled('div', styledOmit$PropsOptions)<{ $isCompact: boolean }>(({ $isCompact }) => ({
    display: 'flex',
    flexDirection: 'column',
    flexGrow: 1,
    gap: "16px",
    padding: !$isCompact ? "8px 16px" : "8px",
    transitionProperty: "padding",
    transitionDuration: "0.5s",
}));

the filtering is based on the function shouldForwardProp in options:

export const styledOmit$PropsOptions = {
    shouldForwardProp: (propName: string) => !propName.startsWith('$')
};

docs on passing the options to the MUI styled: https://mui.com/system/styled/#custom-components

Upvotes: 1

Abd Nour
Abd Nour

Reputation: 11

Customizing prop forwarding in Emotion


use isPropValid from @emotion/is-prop-valid

Example:

import isPropValid from '@emotion/is-prop-valid'
import styled from '@emotion/styled'

const H1 = styled('h1', {
  shouldForwardProp: prop => isPropValid(prop) && prop !== 'color'
})(props => ({
  color: props.color
}))

render(<H1 color="lightgreen">This is lightgreen.</H1>)

NOTE: for Typescript do the following:

const H1 = styled('h1', {
  shouldForwardProp: prop => typeof prop === "string" && isPropValid(prop)
})(props => ({
  color: props.color
}))

check the docs

Upvotes: 1

Sabbin
Sabbin

Reputation: 2445

I have a similar issue with a custom prop on component created with styled from @material-ui/core/styles and it nearly drove me crazy. Using MUI 4.11 the solution with the @emotion/styled did not work for me.

As a solution that worked, I created an intermediate component that doesn't pass the custom props to the DOM.

In the case above, it will look something like

const TypographyComponent = ({myColor, isLarge, ...props}) => <Typography {...props} />;
 
const StyledTypography = styled(TypographyComponent)(
  ({ myColor = "black", isLarge = false }) => ({
    "&&": {
      fontSize: isLarge ? 30 : 16,
      border: `1px solid ${myColor}`,
      margin: 10,
      color: myColor
    }
  })
);

For me this was a viable solution, hope this will help others as well

Upvotes: 3

catchman
catchman

Reputation: 366

Try this

import styled from '@emotion/styled'

const StyledTypography = styled(Typography, {
  shouldForwardProp: (prop) => prop !== "myColor" && prop !== "isLarge"
})(
  ...
);

const StyledButton = styled(Button, {
  shouldForwardProp: (prop) => prop !== "myColor"
})(
  ...
);

Upvotes: 25

Related Questions