emotion
emotion copied to clipboard
How to set global shouldForwardProp?
The problem
I want to pass some common props(such as dynamic class prefix) to styled component through an HOC, and those props are also passed to dom element.
Proposed solution
Can I have a global shouldForwardProp
config or just ignore some props with special charactor prefix?
Alternative solutions
write shouldForwardProp
everytime
const EmotionButton = withCommonProps(styled('div', {
shouldForwardProp: (propName) => propName !== '$prefixCls',
})<WithCommonProps>`
.${(p) => p.$prefixCls}-error-text {
color: red;
}
`)
or put props in theme
function withCommonProps<
ComponentProps extends {} = {},
SpecificComponentProps extends {} = {},
JSXProps extends {} = {}
>(Component: StyledComponent<ComponentProps, SpecificComponentProps, JSXProps>) {
return forwardRef((props, ref) => {
const { prefixCls } = useContext(ConfigContext)
return <Component {...props} ref={ref} theme={{ $prefixCls: prefixCls }} />
}) as ExoticComponent<ComponentProps & SpecificComponentProps & JSXProps>
}
Additional context
@Enivia We ended up exporting and using a wrapped version of the styled.
import { default as emotionStyled } from '@emotion/styled';
import { CreateStyled } from '@emotion/styled';
/**
* Emotion doesn't give the ability to strip out props on convention.
* Add the behavior back in https://github.com/emotion-js/emotion/issues/2193.
*/
export const styled: CreateStyled = ((...args: Parameters<CreateStyled>) =>
emotionStyled(args[0], {
shouldForwardProp: (propName: string) => {
/** Because we are overriding the `shouldForwardProp` to not forward `$` props,
* we have to re-implement the default behavior.
* https://github.com/emotion-js/emotion/blob/b0014b4edc6be047e0a94d8c627d4e52ecccd371/packages/styled/src/utils.js#L40-L47
* This check retains the default emotion behavior for the 'as' prop, using it for html tags and forwarding it for components.
* https://emotion.sh/docs/styled#as-prop
*/
if (propName === 'as') {
return typeof args[0] === 'string' ? false : true;
}
// Removing transient props
return !propName.startsWith('$');
},
...args[1],
})) as unknown as CreateStyled;