Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react-use cannot be imported in Node.js #2353

Open
ocavue opened this issue Jun 20, 2022 · 10 comments · May be fixed by #2596
Open

react-use cannot be imported in Node.js #2353

ocavue opened this issue Jun 20, 2022 · 10 comments · May be fixed by #2596

Comments

@ocavue
Copy link

ocavue commented Jun 20, 2022

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.

  1. Put a package.json under esm/, with the content {"type": "module"};
  2. Or, rename all .js file under esm/ to .mjs;
  3. Or. rename all .js file under lib/ 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
@aamree
Copy link

aamree commented Sep 7, 2022

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?

@nemanja-tosic
Copy link

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

@kaisermann
Copy link

kaisermann commented Jul 10, 2023

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.

@Mange
Copy link

Mange commented Oct 5, 2023

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.

@msurdi
Copy link

msurdi commented Nov 18, 2023

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;

@ThibautMarechal
Copy link

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)

@folushooladipo
Copy link

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.

@folushooladipo
Copy link

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 their default export 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

@real34
Copy link

real34 commented Apr 9, 2024

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"],
    },
  };
});

@tizmagik
Copy link

For reference: https://publint.dev/[email protected]

@oblador oblador linked a pull request Sep 27, 2024 that will close this issue
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants