TypeError: (0 , _react.useEffect) is not a function
Asked Answered
R

8

30

when in the development environment, my app works just fine. When in the production environment it crashes with the error:

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

It happens in a file I created where I import React and useEffect like so:

import React, { useEffect } from 'react'

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

  ...
}

adding a console.log just below this line confirms that useEffect is indeed undefined when in production and the expected function when in dev.

I checked my package.json, yarn.lock & node_modules for any react or react-dom version that might be under 16.8.0 where useEffect was introduced. But everything is 16.13.1 and they are the main dependency and I did try to clean my yarn cache, delete node_modules & yarn.lock, and re-install.

I tried adding and removing it from peerDependencies without success.

I put in a check to make sure there are not 2 separate versions of React running, but saving window.React1 = React inside the library and window.React2 = React inside my application and checking

window.React1 === window.React2 it was true, so that's not it either.

Lastly, I also tried to alias React to the specific one in node_modules, but without any luck.

The only solution I've found that works are if I import it like so:

import React from 'react';

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

But this should be exactly the same as using a destructured import? If I do explicitly use React.useEffect it also forces me to change all of my other useState and useEffect hooks to React.useSate and React.useEffect

The next error just becomes: TypeError: (0 , _react.useState) is not a function in another file where I use React hooks.

I want to solve the problem not implement a workaround.

I use microbundle to bundle my library using React. I use parcel-bundler to import the React-component and render it in a dev environment (directly from src) or prod (the bundled library)

The bundled version I use is bundled with .mjs

I checked the output of the minified .mjs bundle as well and inside React is imported like this:

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

Which looks fine to me.

What I really don't understand is how a restructured import would break it, but just doing React.useEffect would work just fine?

Here's my 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": "**"
  }
}

Also worth noting, it's only React I'm having this problem with. All my other restructured imports work just fine.

Repatriate answered 21/4, 2020 at 16:47 Comment(7)
Using named imports in no way the same as referencing members of the default export. My guess is that, at development time, you have some additional loader in place that's doing some shenanigans to work around legacy compatibility issues between module loadersSypher
can you try the global flag --globals react=React and adding React as peer dependencies <- Although it might not be a proper fix. Look at this issue: github.com/developit/microbundle/issues/537 it looks like coming from yarnCrescen
Could you also try to install microbundle@next to see if that one worked? just to check if it is indeed the current microbundle version issueCrescen
If you're using TypeScript, you might also want to look into this issue: github.com/developit/microbundle/issues/564Crescen
Why are you using the module bundle.mjs instead of the main bundle.js?English
Do you use code splitting?Bookkeeper
My guess is it happened because of using microbundler instead of react-scripts for production build, or something altered bundler configurations in a bad way. I want to draw your attention react hooks names should start with use and may be in this line import ue,{useEffect as pe,useState as fe}from"react"; which useEffect imported as pe something went wrong with react. So, had you tried build with create-react-app and react-scripts?Markmarkdown
R
14

It seem that microbundler does not tolerate to React. This one create bundle that attempt to use react from global scope, instead React that really exposed.

For the same reason your workaround with React.useEffect works as expected, just imagine that it looks like window.React.useEffect.

Here is an example of a primitive application:

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

After bundling with just microbundle it completely broken, but when you try to bundle with

microbundle --globals react=React

as correctly suggest @Jee Mok, it will produce correct bundle. I hope comments will explain what happened.

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

And, by the way, "restructured import " not at all to blame.

Recondition answered 29/4, 2020 at 0:6 Comment(1)
I have the same problem using Webpack instead of Microbundle. I think the problem is the same: the bundle attempt to use react from global scope, instead React . Any idea how I can solve that with Webpack?Salita
C
5

You can fix it by doing:

import React, { useState, useEffect } from "react";
Coloring answered 25/8, 2020 at 19:47 Comment(0)
Y
4

This answer is not for the exact circumstances of the asker, but a possible (albeit very unlikely) solution to the error message in the question title. Since this page is the only result on Google about the error message, I wanted to add this, just in case it helped someone.


I encountered this error too, but I am not using microbundle; I'm using plain old create-react-app with no modifications or anything fancy. The error was only happening in production builds; local development worked fine.

After bashing my head against the wall for an hour, I finally noticed that somehow my IDE had incorrectly auto-imported useEffect like this:

import { useEffect } from "react/cjs/react.development";

instead of this:

import { useEffect } from "react";

Check to make sure your imports are all correct.

I figured this out by taking the specific minified code my browser was complaining about -- in my case, TypeError: (0 , m.useEffect) is not a function -- finding it with ctrl+f in my /build/static/main.blah.js file, observing what code was near it, then tracing it back to the original source file in /src where I discovered the bad import.

Yuhas answered 11/1, 2022 at 6:25 Comment(0)
H
4

i got this error message, but in my case was:

import React, {useEffect } from "react";

try this

useEffect( ()=>{} , []  )

instead of

useEffect=( ()=>{} , []  )
Hypermeter answered 12/5, 2022 at 0:4 Comment(0)
H
0

In my case, it was syntactical. This was when calling the useEffect function into the DOM incorrectly:

Wrong way doubling up on braces:

onInput={{inputHandler}}

Correct way:

onInput={inputHandler}

Homeopathic answered 23/1, 2022 at 10:1 Comment(0)
P
0

In my cases, i work with Next.js. And i've imported hooks { useDispatch, useSelector } from "react-redux";. So they are both working fine, but when i add useEffect. I have error, like in the question. So, to fix . I made import useEffect from 'react', but { useDispatch, useSelector } are still import from 'react-redux'. I'm not sure thats a good practice, to import hooks from different library. But it fixed issues. Hope i help someone.

Proletariat answered 29/7, 2022 at 12:37 Comment(2)
Note: that useEffect hook did not exist in 'react-redux' library.Proletariat
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Foreignborn
C
0

I had a similar issue with TypeError: (0 , _react.useLocation) is not a function (and searching for that error message returned this SO question near the top of the results).

I was importing useLocation() from 'react' instead of from 'react-router-dom'. Rookie mistake, but it could happen to someone else, so I thought I would mention it here.

Cannelloni answered 18/11, 2022 at 18:14 Comment(0)
B
0

In my case, it was

import { useEffect } from "@react-native-community/hooks";

Later I changed it to

import React, {useEffect} from "react";

and it worked.

Beaudoin answered 24/5, 2023 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.