Skip to content

Commit 5d8145d

Browse files
agriffisgregberge
authored andcommitted
fix: x.* must pass through props for as={Component}
This is from discussion at #231 (comment)
1 parent d1c3e3b commit 5d8145d

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

packages/styled-components/src/createX.test.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,40 @@ describe('#createX', () => {
2020
font-size: 10px;
2121
`)
2222
})
23+
24+
it('avoids passing system props to HTML element', () => {
25+
const x = createX<FontSizeProps<Theme>>(fontSize)
26+
const { container } = render(<x.div fontSize={10} />)
27+
expect(container.firstChild).not.toHaveAttribute('fontSize')
28+
})
29+
30+
it('passes HTML attrs to HTML element', () => {
31+
const x = createX<FontSizeProps<Theme>>(fontSize)
32+
const { container } = render(<x.div role="presentation" />)
33+
expect(container.firstChild).toHaveAttribute('role', 'presentation')
34+
})
35+
36+
it('avoids passing system props to "as" component', () => {
37+
const Component = props => <div {...props} />
38+
const x = createX<FontSizeProps<Theme>>(fontSize)
39+
const { container } = render(<x.div as={Component} fontSize={10} />)
40+
expect(container.firstChild).not.toHaveAttribute('fontSize')
41+
})
42+
43+
it('passes non-system props to "as" component', () => {
44+
const Component = ({asdf, ...props}) => <div {...props}>{asdf}</div>
45+
const x = createX<FontSizeProps<Theme>>(fontSize)
46+
const { container } = render(<x.div as={Component} asdf="boo!" />)
47+
expect(container.firstChild).toHaveTextContent('boo!')
48+
})
49+
50+
// skip because this depends on unreleased styled-components 5.2.4 or 6
51+
it.skip('avoids passing non-HTML attrs to HTML element', () => {
52+
const x = createX<FontSizeProps<Theme>>(fontSize)
53+
const { container } = render(<x.div asdf="boo!" />)
54+
expect(container.firstChild).not.toHaveAttribute('asdf')
55+
})
56+
2357
})
2458

2559
describe('#x.extend', () => {

packages/styled-components/src/createX.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,18 @@ export const createX = <TProps extends object>(generator: StyleGenerator) => {
3232
tags.forEach((tag) => {
3333
// @ts-ignore
3434
x[tag] = styled(tag).withConfig({
35-
shouldForwardProp: (prop, defaultValidatorFn) => {
35+
shouldForwardProp: (prop, defaultValidatorFn, elementToBeCreated) => {
3636
if (typeof prop === 'string' && generator.meta.props.includes(prop))
3737
return false
38-
return defaultValidatorFn(prop)
38+
// We must test elementToBeCreated so we can pass through props for
39+
// <x.div as={Component} />. However elementToBeCreated isn't available
40+
// until styled-components 5.2.4 or 6, and in the meantime will be
41+
// undefined. This means that HTML elements could get unwanted props,
42+
// but ultimately this is a bug in the caller, because why are they
43+
// passing unwanted props?
44+
if (typeof elementToBeCreated === 'string')
45+
return defaultValidatorFn(prop)
46+
return true
3947
},
4048
// @ts-ignore
4149
})<TProps>(() => [`&&{`, generator, `}`])

0 commit comments

Comments
 (0)