cuando estoy en el entorno de desarrollo, mi aplicación funciona bien. Cuando en el entorno de producción se bloquea con el error:
Uncaught TypeError: (0 , _react.useEffect) is not a function
Sucede en un archivo que creé donde importo React y useEffect así:
import React, { useEffect } from 'react' const X = () => { useEffect(() => { ... }) ... }agregar un archivo console.log justo debajo de esta línea confirma que useEffect no está definido cuando está en producción y la función esperada cuando está en desarrollo.
Revisé mi paquete.json, yarn.lock y node_modules en busca de cualquier versión de reacción o reacción-dom que pudiera estar por debajo de 16.8.0 donde se introdujo useEffect. Pero todo es 16.13.1 y son la dependencia principal y traté de limpiar mi caché de hilo, eliminar node_modules & yarn.lock y volver a instalar.
Intenté agregarlo y eliminarlo de peerDependencies sin éxito.
Puse una verificación para asegurarme de que no hay 2 versiones separadas de React ejecutándose, pero guardando window.React1 = React dentro de la biblioteca y window.React2 = React dentro de mi aplicación y comprobando
window.React1 === window.React2 era cierto, así que tampoco es eso.
Por último, también intenté crear un alias de React para el específico en node_modules, pero sin suerte.
La única solución que he encontrado que funciona es si la importo así:
import React from 'react'; const X = () => { React.useEffect(() => { ... }) ... } ¿Pero esto debería ser exactamente lo mismo que usar una importación desestructurada? Si uso explícitamente React.useEffect, también me obliga a cambiar todos mis otros ganchos useState y useEffect a React.useSate y React.useEffect
El siguiente error simplemente se convierte en: TypeError: (0 , _react.useState) is not a function en otro archivo donde uso ganchos React.
Quiero resolver el problema, no implementar una solución alternativa.
Uso microbundle para agrupar mi biblioteca usando React. Utilizo parcel-bundler para importar el componente React y renderizarlo en un entorno de desarrollo (directamente desde src) o prod (la biblioteca incluida)
La versión incluida que uso está incluida con .mjs
También verifiqué la salida del paquete .mjs minificado y dentro de React se importa así:
import ue,{useEffect as pe,useState as fe}from"react";
Lo cual me parece bien.
Lo que realmente no entiendo es cómo una importación reestructurada lo rompería, pero simplemente hacer React.useEffect funcionaría bien.
Aquí está mi paquete.json
{ "name": "xxx", "version": "1.1.4", "repository": "git@github.com: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": "**" } }También vale la pena señalar que solo tengo este problema con React. Todas mis otras importaciones reestructuradas funcionan bien.
Parece que microbundler no tolera React. Este crea un paquete que intenta usar react desde el alcance global, en lugar de React que realmente está expuesto.
Por la misma razón, su solución alternativa con React.useEffect funciona como se esperaba, solo imagine que se parece a window.React.useEffect .
Aquí hay un ejemplo de una aplicación primitiva:
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')); Después de agrupar con solo un microbundle , se rompe por completo, pero cuando intenta agrupar con
microbundle --globals react=Reactcomo sugiere correctamente @Jee Mok, producirá el paquete correcto. Espero que los comentarios expliquen lo que sucedió.
!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` eg `this` eg `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>Y, por cierto, "importación reestructurada" no tiene en absoluto la culpa.
Puedes arreglarlo haciendo:
import React, { useState, useEffect } from "react";Esta respuesta no es para las circunstancias exactas del autor de la pregunta, sino para una posible (aunque muy poco probable) solución al mensaje de error en el título de la pregunta. Dado que esta página es el único resultado en Google sobre el mensaje de error, quería agregar esto, en caso de que ayudara a alguien.
También encontré este error, pero no estoy usando microbundle ; Estoy usando create-react-app simple y antigua sin modificaciones ni nada sofisticado. El error solo ocurría en las compilaciones de producción; el desarrollo local funcionó bien.
Después de golpearme la cabeza contra la pared durante una hora, finalmente me di cuenta de que, de alguna manera, mi IDE había importado automáticamente incorrectamente un efecto de useEffect como este:
import { useEffect } from "react/cjs/react.development";en lugar de esto:
import { useEffect } from "react";Verifique que sus importaciones sean todas correctas.
Descubrí esto tomando el código minimizado específico del que se quejaba mi navegador; en mi caso, TypeError: (0 , m.useEffect) is not a function ; lo encontré con ctrl+f en mi /build/static/main.blah.js , observando qué código estaba cerca de él, luego rastreándolo hasta el archivo fuente original en /src donde descubrí la mala importación.
En mi caso, fue sintáctico. Esto fue cuando se llamó incorrectamente a la función useEffect en el DOM:
Manera incorrecta de duplicar los frenos :
onInput={{inputHandler}}
Forma correcta:
onInput={inputHandler}