TypeError: (0, _react.useEffect) ist keine Funktion

9

In der Entwicklungsumgebung funktioniert meine App einwandfrei. In der Produktionsumgebung stürzt es mit dem Fehler ab:

Uncaught TypeError: (0 , _react.useEffect) is not a function

Dies geschieht in einer von mir erstellten Datei, in die ich React importiere und Effect wie folgt verwende:

import React, { useEffect } from 'react'

const X = () => {
  useEffect(() => { ... })

  ...
}

Das Hinzufügen eines console.log direkt unter dieser Zeile bestätigt, dass useEffect in der Produktion tatsächlich undefiniert ist und die erwartete Funktion in dev.

Ich habe meine package.json-, yarn.lock- und node_modules auf React- oder React-Dom-Versionen überprüft, die möglicherweise unter 16.8.0 liegen, wo useEffect eingeführt wurde. Aber alles ist 16.13.1 und sie sind die Hauptabhängigkeit und ich habe versucht, meinen Garncache zu bereinigen, node_modules & yarn.lock zu löschen und neu zu installieren.

Ich habe versucht, es peerDependenciesohne Erfolg hinzuzufügen und zu entfernen .

Ich überprüfe, ob nicht zwei separate Versionen von React ausgeführt werden, sondern speichere window.React1 = Reactin der Bibliothek und window.React2 = Reactin meiner Anwendung und überprüfe

window.React1 === window.React2 es war wahr, also ist es das auch nicht.

Zuletzt habe ich auch versucht, auf den spezifischen in node_modules zu reagieren, aber ohne Glück.

Die einzige Lösung, die funktioniert hat, ist, wenn ich sie so importiere:

import React from 'react';

const X = () => {
  React.useEffect(() => { ... })
  ...
}

Dies sollte aber genau das gleiche sein wie die Verwendung eines destrukturierten Imports? Wenn ich React.useEffect explizit verwende, muss ich auch alle anderen Hooks useState und useEffect in React.useSateund ändernReact.useEffect

Der nächste Fehler wird einfach: TypeError: (0 , _react.useState) is not a functionin einer anderen Datei, in der ich React-Hooks verwende.

Ich möchte das Problem lösen und keine Problemumgehung implementieren.

Ich verwende, microbundleum meine Bibliothek mit React zu bündeln. Ich parcel-bundlerimportiere die React-Komponente und rendere sie in einer Entwicklungsumgebung (direkt von src) oder prod (der gebündelten Bibliothek).

Die von mir verwendete gebündelte Version ist mit .mjs gebündelt

Ich habe auch die Ausgabe des minimierten .mjs-Bundles überprüft und React wird wie folgt importiert:

import ue,{useEffect as pe,useState as fe}from"react";

Was für mich gut aussieht.

Was ich wirklich nicht verstehe, ist, wie ein umstrukturierter Import es kaputt machen würde, aber nur React.useEffect zu machen würde gut funktionieren?

Hier ist meine package.json

{
  "name": "xxx",
  "version": "1.1.4",
  "repository": "[email protected]:xxx/xxx.git",
  "author": "xxx",
  "license": "MIT",
  "source": "src/index.ts",
  "main": "dist/bundle.js",
  "umd:main": "dist/bundle.umd.js",
  "module": "dist/bundle.mjs",
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/@xxx"
  },
  "scripts": {
    "build": "microbundle",
    "dev": "parcel ./test-app/dev/index.html --port 3000",
    "start": "parcel ./test-app/serve/index.html --port 3000",
    "storybook": "start-storybook -s ./public -c .storybook --ci",
    "prepublishOnly": "yarn build"
  },
  "dependencies": {
    "@api-platform/admin": "2.1.0",
    "@api-platform/api-doc-parser": "0.8.2",
    "@fortawesome/fontawesome-svg-core": "^1.2.28",
    "@fortawesome/free-solid-svg-icons": "^5.13.0",
    "@fortawesome/react-fontawesome": "^0.1.9",
    "@material-ui/core": "^4.9.10",
    "@material-ui/icons": "^4.9.1",
    "@react-keycloak/web": "^2.1.1",
    "@types/pluralize": "^0.0.29",
    "google-geocoder": "0.2.1",
    "history": "^4.10.1",
    "keycloak-js": "^9.0.3",
    "lodash.debounce": "^4.0.8",
    "lodash.omit": "^4.5.0",
    "lodash.set": "4.3.2",
    "notistack": "0.9.9",
    "papaparse": "^5.2.0",
    "parcel-bundler": "1.12.4",
    "polished": "^3.5.2",
    "react": "16.13.1",
    "react-admin": "3.4.1",
    "react-dom": "16.13.1",
    "react-is": "16.13.1",
    "react-redux": "^7.2.0",
    "recompose": "^0.30.0",
    "redux": "4.0.5",
    "styled-components": "5.1.0"
  },
  "devDependencies": {
    "@babel/core": "7.9.0",
    "@babel/plugin-syntax-export-default-from": "7.8.3",
    "@babel/preset-env": "7.9.5",
    "@babel/preset-react": "7.9.4",
    "@storybook/addon-a11y": "5.3.18",
    "@storybook/addon-actions": "5.3.18",
    "@storybook/addon-info": "5.3.18",
    "@storybook/addon-knobs": "5.3.18",
    "@storybook/addon-links": "5.3.18",
    "@storybook/addon-storyshots": "5.3.18",
    "@storybook/addon-storysource": "5.3.18",
    "@storybook/addon-viewport": "5.3.18",
    "@storybook/react": "5.3.18",
    "@testing-library/react": "^10.0.3",
    "@types/jsonld": "1.5.1",
    "@types/lodash": "4.14.149",
    "@types/node": "13.11.1",
    "@types/papaparse": "5.0.3",
    "@types/react-redux": "7.1.7",
    "@types/recompose": "^0.30.7",
    "@types/styled-components": "5.1.0",
    "@welldone-software/why-did-you-render": "4.0.7",
    "awesome-typescript-loader": "5.2.1",
    "babel-loader": "^8.1.0",
    "babel-plugin-module-resolver": "4.0.0",
    "babel-plugin-styled-components": "1.10.7",
    "lodash.get": "4.4.2",
    "lodash.uniq": "4.5.0",
    "microbundle": "0.11.0",
    "openapi-types": "1.3.5",
    "parcel-plugin-static-files-copy": "2.3.1",
    "pluralize": "^8.0.0"
  },
  "alias": {
    "jsonld": "./node_modules/jsonld/dist/jsonld.js"
  },
  "staticFiles": {
    "staticPath": "public",
    "watcherGlob": "**"
  }
}

Erwähnenswert ist auch, dass ich nur mit React dieses Problem habe. Alle meine anderen umstrukturierten Importe funktionieren einwandfrei.

MLyck
quelle
Die Verwendung benannter Importe entspricht in keiner Weise der Referenzierung von Mitgliedern des Standardexports. Ich vermute, dass zur Entwicklungszeit ein zusätzlicher Lader vorhanden ist, der einige Spielereien ausführt, um ältere Kompatibilitätsprobleme zwischen Modulladern zu
umgehen
1
Können Sie das globalFlag ausprobieren --globals react=Reactund Reagieren als Peer-Abhängigkeiten hinzufügen? <- Obwohl dies möglicherweise keine ordnungsgemäße Lösung ist. Schauen Sie sich dieses Problem an: github.com/developit/microbundle/issues/537 Es sieht so aus, als käme es vonyarn
Jee Mok
1
Könnten Sie auch versuchen, microbundle @ next zu installieren, um zu sehen, ob dieses funktioniert? Nur um zu überprüfen, ob es sich tatsächlich um das aktuelle Problem mit der Mikrobundle-Version handelt
Jee Mok,
Wenn Sie TypeScript verwenden, sollten Sie sich auch mit diesem Problem befassen
Jee Mok
1
Ich vermute, es ist passiert, weil microbundleranstelle von react-scriptsfür die Produktion Build oder etwas geändert Bundler-Konfigurationen in einer schlechten Weise verwendet. Ich möchte Ihre Aufmerksamkeit auf sich ziehen. React Hooks-Namen sollten mit beginnen useund möglicherweise in dieser Zeile stehen, import ue,{useEffect as pe,useState as fe}from"react";die useEffect importiert, da pebeim Reagieren ein Fehler aufgetreten ist . Hatten Sie versucht, mit create-react-appund zu bauen react-scripts?
Makan

Antworten:

4

Es scheint, dass microbundleres nicht toleriert, zu reagieren. Dieses Paket erstellt ein Paket, das versucht, es reactaus dem globalen Bereich zu verwenden, stattdessen Reactdas wirklich verfügbar ist.

React.useEffectStellen Sie sich aus dem gleichen Grund, wie Ihre Problemumgehung funktioniert, wie erwartet vor, dass es so aussieht window.React.useEffect.

Hier ist ein Beispiel für eine primitive Anwendung:

import ReactDOM from 'react-dom';
import React, { useEffect, useState } from 'react';

/**
 * necessary workaround, microbundle use `h` pragma by default,
 * that undefined when use React
 * another option is to make build with option --jsx
 * @example microbundle --globals react=React --jsx React.createElement
 * yes, yet another workaround
*/
window.h = React.createElement;

const X = () => {
  const [A, B] = useState('world');

  useEffect(() => {
    B('MLyck');
  }, [])

  return `Hello ${A}`;
}

ReactDOM.render(<X />, document.querySelector('react-app'));

Nach dem Bündeln mit nur ist microbundlees komplett kaputt, aber wenn Sie versuchen, mit zu bündeln

microbundle --globals react=React

Wie @Jee Mok richtig vorschlägt, wird es das richtige Bündel produzieren. Ich hoffe, dass Kommentare erklären, was passiert ist.

!function (e, t) {
  "object" == typeof exports && "undefined" != typeof module ?
    t(require("react-dom"), require("react")) :
    "function" == typeof define && define.amd ?
      define(["react-dom", "react"], t) :
      t(e.ReactDOM, e.React);
  /*
  String above is core of problem,
  in case you try to bundle without options `--globals react=React`
  it will looks like: `t(e.ReactDOM, e.react);`
  Obviously `react` is not defined in `e` e.g. `this` e.g. `window`
  due to react expose self as `React`
   */
}(this, function (e, t) {
  e = e && e.hasOwnProperty("default") ? e.default : e, window.h = ("default" in t ? t.default : t).createElement, e.render(h(function () {
    var e = t.useState("world"), n = e[0], r = e[1];
    return t.useEffect(function () {
      r("MLyck");
    }, []), "Hello " + n;
  }, null), document.querySelector("react-app"));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.development.js"></script>

    <react-app></react-app>

Und übrigens "umstrukturierter Import" überhaupt nicht schuld.

Kyr
quelle