emotion version: 10.0.4react version: 16.6.3Relevant code:
let red = css`
color: red;
`;
let green = css`
color: green;
`;
let blue = css`
color: blue;
`;
class Test2 extends React.Component {
render() {
let c = React.Children.map(this.props.children, (child) => (
React.cloneElement(child, {css: red})
));
console.log({props2: this.props}); // This shows children and nothing else
return <div>
<div css={[green]}>Test 2</div>
{c}
</div>;
}
}
class Test3 extends React.Component {
render() {
console.log({props3: this.props}); // This shows the css object provided by Test2
return <div css={[blue]}>Test 3</div>;
}
}
const App = () => {
return (
<div>
<div css={[red]}>Test</div>
<Test2><Test3 /></Test2>
</div>
);
};
What you did:
I am attempting to migrate several libraries and an application to Emotion 10. A lot of the React components in this project are dynamically generated, and have to have styling provided from data sources. This worked fine when we used className, cx(), and cloneElement to inject these styles into child components.
What happened:
When I dynamically apply the css prop to a child component via cloneElement, it is not picked up or used. In the example code above, "Test 3" should come out red, but instead is blue. This is not a case of blue taking precedence; adding another style such as font-style: italic to red will make Test italic, but not Test 3.
Is there a way to fix this that does not involve using the legacy className solution?
css prop relies on jsx (which is an alternative to React.createElement), you'd have to do this:
import { jsx } from '@emotion/core'
const cloneElement = (element, props) =>
jsx(element.type, {
key: element.key,
ref: element.ref,
...element.props
...props,
});
// ...
let c = React.Children.map(this.props.children, (child) => (
cloneElement(child, {css: red})
));
This worked, thank you!
Most helpful comment
cssprop relies onjsx(which is an alternative toReact.createElement), you'd have to do this: