Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

npm ls react can show one version and still fail to reveal why an app has two React module instances. It reports npm’s logical dependency tree, not a definitive inventory of every installed directory or the modules a runtime or bundler actually loads. To find the cause, compare React’s resolved path from the app and from any linked library, then fix the package metadata or resolver configuration responsible.

Why npm ls can miss a second React copy

npm ls describes dependency relationships in npm’s logical tree; it is not a complete map of physical node_modules placement. Its default output can also be shallow. Meanwhile, Node or a bundler resolves each import from the importing package’s location and configuration. A linked library or nested package can therefore load React from another path even when the listing appears to show one version.

React’s relevant requirement is module identity: the react imported by application code must resolve to the same module as the react imported inside react-dom. Equal version labels do not prove that they are the same module. A second copy can coexist harmlessly in some architectures, such as an isolated third-party widget; the problem is when parts of the same component tree use different React instances. React: Invalid Hook Call Warning

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How to check which React each package resolves

  1. From the application root, list all dependency paths: run npm ls --all react (equivalently, npm ls react --all). This expands the logical tree beyond npm’s default shallow view and can expose multiple dependency paths or versions, but it does not prove which physical module a runtime loads. npm ls documentation
  2. Inspect installed placement and links: run npm ls -l react, then inspect the relevant linked package and its nested node_modules directories if placement remains unclear. The logical tree and physical placement answer different questions.
  3. Compare resolution from each importer: use require.resolve('react') from the app’s package context and from the component library or workspace package that imports React. In CommonJS, different resolved paths indicate distinct module identities; matching version text is not enough. Node resolves dependencies relative to the calling module and, by default, dereferences symlinks to real paths. Node.js modules documentation

If the paths differ, check whether the library’s own manifest or the bundler is introducing the second resolution. If they match but the warning persists, inspect the actual runtime or bundle resolution rather than relying on the npm listing alone.

Fix the cause that creates the second resolution

Correct a component library’s dependency declaration

A reusable React component library generally should declare React as a peerDependency, rather than as an ordinary dependency that causes consumers to install a private copy. Check the library’s package.json and correct its dependency metadata when that is the cause. React identifies this packaging mistake as a way an app and library can end up using different React modules. React: Invalid Hook Call Warning

Try npm deduplication, then verify again

npm find-dupes runs deduplication in dry-run mode, so it can show what npm would change without applying it. npm dedupe can reorganize compatible installed packages, but it does not update semver ranges for direct dependencies in package.json. After deduplication, repeat the resolution-path checks and validate the app; a tidier dependency tree alone does not establish runtime identity. npm find-dupes · npm dedupe

Configure the bundler when package layout requires it

For Vite, resolve.dedupe can force dependencies such as React to resolve from the project root, which can help with hoisted or linked-package layouts. Vite documents a limitation for SSR builds using ESM outputs configured through build.rollupOptions.output; account for that caveat before relying on this setting. Vite shared options

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For webpack, inspect resolve.alias and resolve.symlinks. Aliases take precedence, while webpack’s default symlink behavior resolves linked resources to their real paths, which can affect dependency lookup with npm link. webpack resolve configuration

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Confirm the fix by checking module identity

  • Compare the resolved React path from the app and from each package that imports React.
  • Check that the react used by application code and the one used by react-dom resolve to the same module.
  • After changing package metadata, deduplicating, or adjusting bundler configuration, run the path checks again and validate the application in its actual runtime or build mode.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.