react icon indicating copy to clipboard operation
react copied to clipboard

TypeError: Cannot read property 'setExtraStackFrame' of undefined

Open IMMC opened this issue 4 years ago • 27 comments

I try Upgrade to the New JSX Transform in my project.(According to the official tutorial.) I used production react in development environment,I see this error. but, if used development react in development environment, every thing is ok.

React version: 17.0.1

The current behavior

TypeError: Cannot read property 'setExtraStackFrame' of undefined

Additional information

react.production.min.js:22 Uncaught TypeError: Cannot read property 'setExtraStackFrame' of undefined at setCurrentlyValidatingElement (react-jsx-runtime.development.js:574) at checkPropTypes (react-jsx-runtime.development.js:618) at validatePropTypes (react-jsx-runtime.development.js:1072) at jsxWithValidation (react-jsx-runtime.development.js:1192) at jsxWithValidationDynamic (react-jsx-runtime.development.js:1209) at PartPage (PartPage.js:161) at Le (react-dom.production.min.js:100) at Re (react-dom.production.min.js:113) at Pj (react-dom.production.min.js:232) at di (react-dom.production.min.js:168)

IMMC avatar Dec 01 '20 09:12 IMMC

This looks like you're transpiling to the JSX runtime for development while using react in production. Could you provide a complete, minimal reproduction of the issue?

eps1lon avatar Dec 01 '20 15:12 eps1lon

React v17.0.1

There are two errors in the file:react-jsx-dev-runtime.development.js

1

var loggedTypeFailures = {};
var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;

function setCurrentlyValidatingElement(element) {
  {
    if (element) {
      var owner = element._owner;
      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);
      ReactDebugCurrentFrame.setExtraStackFrame(stack);
    } else {
      ReactDebugCurrentFrame.setExtraStackFrame(null);
    }
  }
}

component pseudo code:

import { Tabs, Empty } from 'antd';
const { TabPane } = Tabs;

 const Com = () => {
   return (
     <Tabs>
       <TabPane tab="全部" key="all">
          {data.length ? (
            <Row type="flex" gutter={16} key='all_row'>
              {data.map((d: any, index: number) => {
                if (true) {
                  return (
                    <Col
                      key={index}
                      style={{ marginTop: 16 }}
                    >
                      {renderChildCom}
                    </Col>
                  );
                }
                return (
                  <Col
                    key={index}
                    style={{ marginTop: 16 }}
                  >
                    {renderOtherChildCom}
                  </Col>
                );
              })}
            </Row>
          ) : (
            <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} key="all_empty" />
          )}
      </TabPane>
    </Tabs>
  )
}

export default Com;

2

// In this scenario, an error is reported by adding a key
var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;
var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;

function setCurrentlyValidatingElement$1(element) {
  {
    if (element) {
      var owner = element._owner;
      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);
      ReactDebugCurrentFrame$1.setExtraStackFrame(stack);
    } else {
      ReactDebugCurrentFrame$1.setExtraStackFrame(null);
    }
  }
}

boychina avatar Dec 17 '20 04:12 boychina

Running into the same issue here. It's caused by a environment mismatch between react and jsx runtime.

In my case, I'm using webpack & babel to build my application. React is excluded from the application bundle and is included from CDN. The included react is the production build of v17.0.1. Meanwhile, the application code is transformed by babel and is bundled via webpack in development mode.

The problem is that the new jsx transform will import jsx context from react/jsx-runtime, which will dynamically import either the production build or the development build according to NODE_ENV environment variable.

'use strict';

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./cjs/react-jsx-runtime.production.min.js');
} else {
  module.exports = require('./cjs/react-jsx-runtime.development.js');
}

Since the application is bundled in development mode, react-jsx-runtime.development.js is required, which assumes that ReactDebugCurrentFrame exists. However, the actual react build being used is a production build, in which ReactDebugCurrentFrame is not initialized. See source code here.

To solve this problem, either include the development react build from CDN or set the NODE_ENV to production in building process.

I think it would be better to let users pass the environmental variable as an option to the babel preset to determine which build of react they want to use.

hueyhe avatar Dec 28 '20 09:12 hueyhe

In my case, I'm using webpack & babel to build my application. React is excluded from the application bundle and is included from CDN.

Is react/jsx-runtime also excluded from the application bundle and included via CDN?

eps1lon avatar Dec 28 '20 09:12 eps1lon

Is react/jsx-runtime also excluded from the application bundle and included via CDN?

In my case no. The entry of react/jsx-runtime is bundled into the application js file.

hueyhe avatar Dec 28 '20 09:12 hueyhe

Is react/jsx-runtime also excluded from the application bundle and included via CDN?

@eps1lon Excluding react/jsx-runtime from the application bundle and including it via CDN could be a solution. But it seems a little bit weird to include react/jsx-runtime manually because it's not a required dependency like react and react-dom. Also, introducing a new dependency seems against the purpose of the new jsx transform in the first place. Maybe it should be bundled together with react?

hueyhe avatar Dec 28 '20 12:12 hueyhe

But it seems a little bit weird to include react/jsx-runtime manually because it's not a required dependency like react and react-dom.

react/jsx-runtime is just the entrypoint. It is actually in the react package. By bundling react/jsx-runtime in the application bundle and react via CDN you're duplicating code because react/jsx-runtime depends on react. If you bundle react/jsx-runtime you also bundle react.

eps1lon avatar Dec 28 '20 14:12 eps1lon

If you bundle react/jsx-runtime you also bundle react.

react/jsx-runtime is indeed bundled, but react is excluded from the bundle because it's marked as external. react code is not duplicated. The problem is that the code of the entrypoint doesn't match the referenced react build. Here is a minimal reproduction of this issue.

hueyhe avatar Dec 29 '20 03:12 hueyhe

Yeah it isn't a bundling issue. Sorry for the confusion.

The issue is that you're transpiling in development (i.e. NODE_ENV=production) but using react's production build from the CDN.

These environments (just like versions) need to match right now. So for development you want to apply

diff --git a/dist/index.html b/dist/index.html
index 4dd8259..47f53e3 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -6,8 +6,8 @@
   </head>
   <body>
     <div id="react-root"></div>
-    <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
-    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
+    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
+    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
     <script src="./bundle.js"></script>
   </body>
 </html>

and for production

diff --git a/package.json b/package.json
index 9d0625c..212cd6d 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
   "repository": "https://github.com/hueyhe/react-jsx-runtime-mismatch.git",
   "author": "[email protected]",
   "scripts": {
-    "start": "webpack serve --config ./webpack.config.js --mode development"
+    "start": "webpack serve --config ./webpack.config.js --mode production"
   },
   "devDependencies": {
     "@babel/core": "^7.12.10",

Applying both patches at the same time will cause issues similar to the reported one.

How you reconcile these patches is up to you. But the fact remains that environments need to match right now.

@gaearon Is there precedent for supporting a mix of environments e.g. react's prod build with react-dom's dev build or (like this case) react's prod build with react/jsx-runtime's dev build? Otherwise we can close this issue as far as I can tell.

eps1lon avatar Dec 29 '20 10:12 eps1lon

Thank you for the clarification. But based on my testing, applying both changes won't cause similar issues here because the development related code is stripped out in the production bundle.

I agree that environments should match between dependencies that are internally coupled, e.g. react and react/jsx-transform in this case, but it's not necessary for the application environment to match the environment of dependencies. For example, I could use either prod build or dev build of lodash, which won't make any difference, in my application code.

I think the topic we should discuss here is not whether to support a mix of environments, but where should we place react/jsx-runtime. It's a new dependency introduced by the new jsx transform. If it's bundled together with the application code, environments between application and react have to match. But if it's included as an external, like react and react-dom, then there's no need to match the environments, which I think is more reasonable.

hueyhe avatar Dec 29 '20 12:12 hueyhe

Generally I don't think you should bundle dependencies assuming different environments. A bundle should only target a single environment not a mix. Some particular combinations "working" is not an argument that you should do it.

Similarly, you can't import react with Symbol not available and then import react-dom with Symbol available. That is already problematic and I would consider changing NODE_ENV during bundle "lifetime" also incorrect.

I think the topic we should discuss here is not whether to support a mix of environments

I agree. I already asked a core member above what they think.

But if it's included as an external, like react and react-dom, then there's no need to match the environments, which I think is more reasonable.

Not necessarily. You could still not match a dev jsx runtime with a prod react bundle which you're currently doing. This is not a bundling issue but environment issue.

eps1lon avatar Dec 29 '20 13:12 eps1lon

Similarly, you can't import react with Symbol not available and then import react-dom with Symbol available.

Yeah you're right. Environments among react, react-dom, and react/jsx-runtime should match. That's why I think react/jsx-runtime should be treated just the same as react and react-dom, i.e. as an external.

A bundle should only target a single environment not a mix.

I also agree with you here. But from my perspective, when react, react-dom, and react/jsx-transform are marked as externals, they're not part of the application bundle, but together an external "react bundle". Either bundle should target a single environment respectively. As long as the prod build and the dev build of the "react bundle" have the same API (which I think is expected), the caller, i.e. the application bundle, has no need to worry about which build it depends on.

// No need to care about whether dev build or prod build of react is being used here
// because no matter under what environment the application code is being transpiled and bundled,
// the application code always relies on the same react API, i.e. `React.createElement`,
// which both dev and prod build of react would expose.
import React from 'react';

function App() {
  return <h1>Hello World</h1>;
}

hueyhe avatar Dec 30 '20 03:12 hueyhe

Added key in mapping; image problem fixed

If you make a mistake inside the map loop you will get this error.

ahmetcaglayan avatar Jul 07 '22 11:07 ahmetcaglayan

thanks @ahmetcaglayan! thats a new error to see for the key missing.

michaeljwiebe avatar Jul 15 '22 19:07 michaeljwiebe

thank you so much! that was the result on our side as well. That is such a obscure error for a key missing XD

tfrost57 avatar Jul 22 '22 14:07 tfrost57

I think this should be just a user (dev) friendly message "hey, your key prop is missing!", and the error can stay

kneczaj-p44 avatar Aug 03 '22 10:08 kneczaj-p44

Hi , Getting a same error Was trying to run micro frontend on UAT getting this error. Works fine with local. Just don't work with UAT and PROD. Updated to latest node - 18.16.0.

image

Cannot read properties of undefined (reading 'setExtraStackFrame') Call Stack  setCurrentlyValidatingElement$1   vendors-node_modules_react_jsx-runtime_js.1787bdda.chunk.js:972:32  validateExplicitKey   vendors-node_modules_react_jsx-runtime_js.1787bdda.chunk.js:1085:5  validateChildKeys   vendors-node_modules_react_jsx-runtime_js.1787bdda.chunk.js:1114:11  jsxWithValidation   vendors-node_modules_react_jsx-runtime_js.1787bdda.chunk.js:1275:15  jsxWithValidationStatic   vendors-node_modules_react_jsx-runtime_js.1787bdda.chunk.js:1305:12

Anyone can help me with this.?

KshitijGhodekar-07 avatar Jun 03 '23 20:06 KshitijGhodekar-07

Double-check that:

  • the version of react/jsx-runtime matches the version of react on the page
  • theNODE_ENV that react/jsx-runtime and react were built in match

guym4c avatar Jul 19 '23 14:07 guym4c

In my case, it was react-table v7. Removing the key to permit using the one that comes from cell.getCellProps() fixed the issue

Before After
Screenshot 2023-10-25 at 11 51 46 Screenshot 2023-10-25 at 11 55 11

dennisja avatar Oct 25 '23 09:10 dennisja

@KshitijGhodekar-07 I have exactly the same problem as you.

The problem seems to stem from the fact that you are attempting to use a development build on a host that you built for production.

React, in production, loads "react-jsx-runtime.production.js" instead of "react-jsx-runtime.development.js."

In the react-jsx-runtime.production.js, the ReactDebugCurrentFrame object, where the setExtraStackFrame() method is present, is not available.

I, too, need to inject remotes in development mode (locally) on a production host and am looking for a viable solution.

icrocket avatar Nov 22 '23 15:11 icrocket