TypeError: (0, _react.useEffect) bukan fungsi

9

ketika di lingkungan pengembangan, aplikasi saya berfungsi dengan baik. Ketika berada di lingkungan produksi, crash dengan kesalahan:

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

Ini terjadi pada file yang saya buat di mana saya mengimpor Bereaksi dan menggunakan Efek seperti:

import React, { useEffect } from 'react'

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

  ...
}

menambahkan console.log tepat di bawah baris ini menegaskan bahwa useEffect memang tidak terdefinisi saat dalam produksi dan fungsi yang diharapkan saat dalam dev.

Saya memeriksa package.json, yarn.lock & node_modules saya untuk versi reaksi atau reaksi dom yang mungkin di bawah 16.8.0 di mana useEffect diperkenalkan. Tapi semuanya 16.13.1 dan mereka adalah ketergantungan utama dan saya memang mencoba untuk membersihkan cache benang saya, menghapus node_modules & yarn.lock, dan menginstal ulang.

Saya mencoba menambahkan dan menghapusnya peerDependenciestanpa hasil.

Saya memberi tanda centang untuk memastikan tidak ada 2 versi terpisah dari React running, tetapi menyimpan window.React1 = Reactdi dalam perpustakaan dan window.React2 = Reactdi dalam aplikasi saya dan memeriksa

window.React1 === window.React2 itu benar, jadi bukan itu juga.

Terakhir, saya juga mencoba alias Bereaksi dengan yang spesifik di node_modules, tetapi tidak berhasil.

Satu-satunya solusi yang saya temukan yang berfungsi adalah jika saya mengimpornya seperti ini:

import React from 'react';

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

Tetapi ini harus persis sama dengan menggunakan impor yang dirusak? Jika saya secara eksplisit menggunakan React.useEffect itu juga memaksa saya untuk mengubah semua useState saya yang lain dan menggunakan hooksEffect untuk React.useSatedanReact.useEffect

Kesalahan berikutnya hanya menjadi: TypeError: (0 , _react.useState) is not a functiondi file lain di mana saya menggunakan React hooks.

Saya ingin menyelesaikan masalah tidak menerapkan solusi.

Saya gunakan microbundleuntuk menggabungkan perpustakaan saya menggunakan Bereaksi. Saya menggunakan parcel-bundleruntuk mengimpor komponen-React dan merendernya di lingkungan dev (langsung dari src) atau prod (perpustakaan yang dibundel)

Versi bundel yang saya gunakan dibundel dengan .mjs

Saya memeriksa output dari berkas .mjs yang diperkecil juga dan di dalam Bereaksi diimpor seperti ini:

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

Yang terlihat baik untuk saya.

Apa yang saya benar-benar tidak mengerti adalah bagaimana impor yang direstrukturisasi akan mematahkannya, tetapi hanya melakukan React.useEffect akan bekerja dengan baik?

Ini paket saya. 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": "**"
  }
}

Juga patut dicatat, hanya React saya mengalami masalah dengan ini. Semua impor saya yang direstrukturisasi berhasil dengan baik.

MLyck
sumber
Menggunakan impor yang disebutkan sama sekali tidak sama dengan mereferensikan anggota dari ekspor default. Dugaan saya adalah, pada saat pengembangan, Anda memiliki beberapa loader tambahan di tempat yang melakukan beberapa gangguan untuk mengatasi masalah kompatibilitas warisan antara pemuat modul
Aluan Haddad
1
dapatkah Anda mencoba globalbendera --globals react=Reactdan menambahkan Bereaksi sebagai dependensi rekan <- Meskipun mungkin itu bukan perbaikan yang tepat. Lihatlah masalah ini: github.com/developit/microbundle/issues/537 sepertinya berasal dariyarn
Jee Mok
1
Bisakah Anda juga mencoba menginstal microbundle @ di sebelah untuk melihat apakah itu berhasil? hanya untuk memeriksa apakah itu memang masalah versi microbundle saat ini
Jee Mok
Jika Anda menggunakan TypeScript, Anda mungkin juga ingin melihat ke dalam masalah ini: github.com/developit/microbundle/issues/564
Jee Mok
1
Dugaan saya adalah itu terjadi karena menggunakan microbundleralih-alih react-scriptsuntuk membangun produksi, atau sesuatu mengubah konfigurasi bundler dengan cara yang buruk. Saya ingin menarik perhatian Anda, reaksi nama kait harus dimulai dengan usedan mungkin di baris ini import ue,{useEffect as pe,useState as fe}from"react";yang menggunakan Efek diimpor sebagai pesesuatu yang salah dengan reaksi. Jadi, sudahkah Anda mencoba membangun dengan create-react-appdan react-scripts?
Makan

Jawaban:

4

Tampaknya microbundlertidak tahan untuk Bereaksi. Yang ini membuat bundel yang berusaha digunakan reactdari lingkup global, alih React- alih yang benar-benar terbuka.

Untuk alasan yang sama dengan solusi yang React.useEffectdiharapkan, bayangkan saja seperti itu window.React.useEffect.

Berikut adalah contoh aplikasi primitif:

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'));

Setelah bundling hanya dengan microbundleitu benar-benar rusak, tetapi ketika Anda mencoba untuk mengikat

microbundle --globals react=React

seperti yang disarankan dengan benar @ Ya ampun, itu akan menghasilkan bundel yang benar. Saya harap komentar akan menjelaskan apa yang terjadi.

!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>

Dan, omong-omong, "impor yang direstrukturisasi" sama sekali tidak bisa disalahkan.

Kyr
sumber