Reputation: 7470
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 lowercaseislarge
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
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
Reputation: 11
use isPropValid from @emotion/is-prop-valid
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
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
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