-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
emotion
version: 9.2.9react
version: 16.5.0
Relevant code.
import styled from '@emotion/native'
import isPropValid from '@emotion/is-prop-valid'
const Text = styled.Text(props => ({
fontFamily: "Lato"
}))
const Headline = styled(Text, { shouldForwardProp: isPropValid })(props => ({
color: props.isColored ? props.theme.baseColor : props.theme.textColor,
fontWeight: '700'
}))
<Headline isColored>Hello, World!</Headline>
What you did:
I'm using react-native and react-testing-library together with react-native-web to test my components.
I added { shouldForwardProp: isPropValid }
to my styled components in react native to prevent the prop isColored
from being forwarded.
What happened:
Using the setup described above, I noticed that the prop isColored
is being forwarded. The following error message will be displayed:
Warning: React does not recognize the isColored prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase iscolored instead. If you accidentally passed it from a parent component, remove it from the DOM element.
Problem description:
It seems like shouldForwardProp
isn't being called in @emotion/native. I tried passing a console.warn
to see if shouldForwardProp
will be called, but nothing will be logged.
const shouldForwardProp = () => {
console.warn('shouldForwardProp called')
}
const Headline = styled(Text, { shouldForwardProp })(...))
Suggested solution:
@emotion/native uses createStyled
from @emotion/primitives-core:
emotion/packages/native/src/styled.js
Lines 1 to 7 in 7a4ff8e
import { StyleSheet } from 'react-native' | |
import { createStyled } from '@emotion/primitives-core' | |
/** | |
* a function that returns a styled component which render styles in React Native | |
*/ | |
let styled = createStyled(StyleSheet) |
primitives-core has a default implementation for shouldForwardProp
:
emotion/packages/primitives-core/src/styled.js
Lines 7 to 16 in 7a4ff8e
let defaultPickTest = prop => prop !== 'theme' && prop !== 'innerRef' | |
type options = { | |
getShouldForwardProp: (cmp: React.ElementType) => (prop: string) => boolean | |
} | |
export function createStyled( | |
StyleSheet: Object, | |
{ getShouldForwardProp = () => defaultPickTest }: options = {} | |
) { |
It seems like @emotion/native doesn't override this default implementation. It should provide an API to pass shouldForwardProp
as option.
Or maybe there is an API for it which isn't documented, or I can't find the documentation, or I can't find a way to do it in the emotion package code.
There is a discussion regarding this in the PR for @emotion/native: https://github.com/emotion-js/emotion/pull/759/files#r204662931
But to be totally honest, I don't understand why the API is intentionally different in comparison to @emotion/styled-base:
emotion/packages/styled-base/src/index.js
Lines 20 to 34 in 7a4ff8e
let createStyled: CreateStyled = (tag: any, options?: StyledOptions) => { | |
if (process.env.NODE_ENV !== 'production') { | |
if (tag === undefined) { | |
throw new Error( | |
'You are trying to create a styled element with an undefined component.\nYou may have forgotten to import it.' | |
) | |
} | |
} | |
let identifierName | |
let shouldForwardProp | |
let targetClassName | |
if (options !== undefined) { | |
identifierName = options.label | |
targetClassName = options.target | |
shouldForwardProp = |