question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`jsx(…)` fails when “cloning” element with `css` prop

See original GitHub issue

Current 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.6
  • emotion version: 10.0.10

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:18 (9 by maintainers)

github_iconTop GitHub Comments

7reactions
ryanswansoncommented, Jun 21, 2019

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)

import {jsx} from '@emotion/core';

export default function cloneElement(element, config, ...children) {
  return jsx(
    element.props['__EMOTION_TYPE_PLEASE_DO_NOT_USE__']
      ? element.props['__EMOTION_TYPE_PLEASE_DO_NOT_USE__']
      : element.type,
    {
      key: element.key !== null ? element.key : undefined,
      ref: element.ref,
      ...element.props,
      ...config,
    },
    ...children,
  );
}

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.

2reactions
Andaristcommented, Oct 28, 2019

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).

Read more comments on GitHub >

github_iconTop Results From Across the Web

inline event handlers not working after cloning in react.js
Hello everybody i am observing an issue when trying to clone a react component(cloning the parent div of react component) which makes the ......
Read more >
How to use React.cloneElement() function?
The resultant element would have the initial element's props mixed in shallowly with the new props. ... Cloning an element with React.
Read more >
How to pass data to a React component's props.children
React makes it easy to pass children to reusable components. ... merge new props into the elements passed to props.children by cloning them....
Read more >
How to Create and Publish a React Component Library
You can try cloning the repo linked at the top of the tutorial which has a working version all combined together, and then...
Read more >
react-tabs
Tab; TabPanel; TabList; Tabs. Pass through properties. Note: Because of how react-tabs works internally (it uses cloning to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found