`jsx(…)` fails when “cloning” element with `css` prop
See original GitHub issueCurrent behavior:
When attempting to use jsx
to replace React.cloneElement
on a component with a css
prop, React throws the following error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.
I suspect this has something to do with the context nodes being inserted around elements that use the css
prop, but I don’t really grok the internals of Emotion or React well enough to understand how to resolve the issue.
To reproduce:
I’ve created a CodeSandbox demonstrating the issue here. If you remove the css
prop from the h1
the operation will succeed.
Expected behavior:
jsx(element, {})
should behave similarly to React.createElement
or React.cloneElement
.
Environment information:
react
version: 16.8.6emotion
version: 10.0.10
Issue Analytics
- State:
- Created 4 years ago
- Comments:18 (9 by maintainers)
Top GitHub Comments
We encountered this issue / error as well and have a potential solution that should ultimately live within the emotion library.
Diagnosis
Using jsx pragma for components with a css prop works fine. Using the jsx function directly as a cloneElement substitute works fine. We encountered the error above when combining both uses of the jsx function, e.g. the element returned from a jsx call via pragma being passed again to a jsx call when cloning a child.
We found that the jsx function stores type information in a private prop: __EMOTION_TYPE_PLEASE_DO_NOT_USE__. When cloning the element returned from the original jsx call, the type should conditionally be pulled from the private prop rather than element.type (see code below).
Our solution (partial)
What is missing?
There are probably additional things that a cloneElement function should do similar to that in React, such as validating config.ref and config.key.
Library Consideration
The primary reason to consider adding a cloneElement equivalent into the emotion library proper is to maintain the abstraction over the private prop (__EMOTION_TYPE_PLEASE_DO_NOT_USE__). Otherwise, the code example from #1102 was sufficient.
I’m going through all of the issues right now (tackled nearly 80 of them in the last couple of days, which has included answering to them - sometimes comprehensively, giving guidance, creating dozens of PRs etc). Once I get through it all - I will have to implement what can be implemented without breaking changes (just few minor improvements) and then I will be able to proceed with v11, which is not expected to have major breaking changes (like v10 did).
Hard to give an exact estimate as this is all done in my free time, but I move things forward on a daily basis right now. It’s also not guaranteed that v11 will fix this, but I have every intention of trying to figure out a solution that would cover this (0-config SSR seems to be the biggest challenge in this regard).