react-use cannot be imported in Node.js
What is the current behavior?
I can't use ESM syntax to import react-use in Node.js. I found this issue when I try to run some unit tests on Node.js.
The reason for this issue is that the following package.json is not supported by Node.js. There is a detailed explanation https://github.com/sheremet-va/dual-packaging
{
"name": "react-use",
"main": "lib/index.js",
"module": "esm/index.js",
...
}
There are some simple methods to fix this issue. More explanation in the link above.
- Put a
package.jsonunderesm/, with the content{"type": "module"}; - Or, rename all
.jsfile underesm/to.mjs; - Or. rename all
.jsfile underlib/to.cjs.
Steps to reproduce it and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have extra dependencies other than react-use. Paste the link to your JSFiddle or CodeSandbox example below:
bash-3.2$ pnpm add react-use
dependencies:
+ react-use 17.4.0
bash-3.2$
bash-3.2$ echo 'import {useDefault} from "react-use"' > a.mjs
bash-3.2$
bash-3.2$ node a.mjs
file:///private/tmp/a.mjs:1
import {useDefault} from "react-use"
^^^^^^^^^^
SyntaxError: Named export 'useDefault' not found. The requested module 'react-use' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'react-use';
const {useDefault} = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:128:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:194:5)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
What is the expected behavior?
react-use can be imported in a .mjs file with ESM syntax.
A little about versions:
- OS: macOS
- Browser (vendor and version): N/A
- React: N/A
- Node: 16.15
-
react-use: 17.4.0 - Did this worked in the previous package version?: No
bash-3.2$ pnpm add react-use dependencies:
- react-use 17.4.0 bash-3.2$ bash-3.2$ echo 'import {useDefault} from "react-use"' > a.mjs bash-3.2$ bash-3.2$ node a.mjs file:///private/tmp/a.mjs:1 import {useDefault} from "react-use" ^^^^^^^^^^ SyntaxError: Named export 'useDefault' not found. The requested module 'react-use' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:
import pkg from 'react-use'; const {useDefault} = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:128:21) at async ModuleJob.run (node:internal/modules/esm/module_job:194:5) at async Promise.all (index 0) at async ESMLoader.import (node:internal/modules/esm/loader:385:24) at async loadESM (node:internal/process/esm_loader:88:5) at async handleMainPromise (node:internal/modules/run_main:61:12)
I also faced this problem. Is there a temporary solution?
I use a setup where react-use is imported by both a node module (node 16) and nextjs - node cannot use named exports reliably for CJS and if i use the default export format, then nextjs' build fails saying that there isn't a default export (because there isn't, seeing how it's node's interop that adds it). Using a namespace import leads to Node not recognizing all default re-exports.
Direct file import such as
import useUpdateEffect from 'react-use/lib/useUpdateEffect.js';
leads to
{ default: [Function: useUpdateEffect] }
Needless to say, ESM CJS interop is a mess...
I'm getting the same issue. I'm updating my app to react@18 and next@13, which automatically supports properly-packaged esm packages. However, as stated by the OP, a .mjs file can't import a .js file even though its contents are ESM. Is it possible to export the esm version as .mjs files?
edit:
It seems that it's possible to add a package.json with { type: module } in the dist/esm/ directory, but I'm not sure how that would affect existing projects that are using the current esm exports.
This seems to happen to me to using Remix. Everything should be ESM, but I still get server-side errors trying to import the library.
I'll have to move over to some other hooks library.
Just found this issue. In case it helps somebody else, here's my workaround until the underlying problem is resolved:
import useKeyLib from "react-use/lib/useKey.js";
const useKey = useKeyLib.default;
I have the same issue. I made a quick reproduction with remix, using the create-remix, then I added react-use. Any recommended import is failing to compile. (repro: https://github.com/ThibautMarechal/react-use-in-remix)
I am also experiencing the issue when using Remix. This import error is a real downside to using this awesome library. I hope there will be a fix soon.
Also, for anyone using TypeScript and Remix, here's another possible workaround that extends @msurdi 's own:
- create a file in your project into which you'll import the hooks you need from
react-use, patch theirdefaultexport issues and then export the hooks for all your components to use. - Patch the hooks like this:
import useKeyPressEventLib from 'react-use/lib/useKeyPressEvent'
export const useKeyPressEvent = (useKeyPressEventLib as any).default as typeof useKeyPressEventLib
For Vite-based projects (& Remix), this configuration should also solve the issue:
// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig((env) => {
return {
// […]
ssr: {
noExternal: ["react-use"],
},
optimizeDeps: {
include: ["react-use"],
},
};
});
For reference: https://publint.dev/[email protected]