Skip to content

[BUG] Workspaces hoisted package is not resolving to dependent's peer dependencies #2989

@ruluva

Description

@ruluva

Current Behavior:

I have a project using multiple workspaces. For simplicity I created a smaller project that reproduces the issue.
I am using @testing-library/react to help with some unit tests, and I have pulled in the required peer dependencies of react and react-dom. Each package is using its own version of React, one is using 17.0.1 and the other 17.0.2. Both are using the same @testing-library/react package version. The hoisted packages are react (17.0.2), react-dom (17.0.2) and @testing-library/react (11.2.5). Package b has its own React versions for react and react-dom in its local node_modules. I have both projects using the @testing-library/react render function in a set of test files. When I run jest on project a, it passes without issue. When I run jest on project b (with its local versions), it fails with the following error:

package-b@1.0.0 test
jest

FAIL tests/components/App.test.tsx
● Console

console.error
  Error: Uncaught [Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
  See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.]
      at reportException (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:62:24)
      at innerInvokeEventListeners (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9)
      at invokeEventListeners (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
      at HTMLUnknownElementImpl._dispatch (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
      at HTMLUnknownElementImpl.dispatchEvent (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLUnknownElement.dispatchEvent (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
      at Object.invokeGuardedCallbackDev (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:3994:16)
      at invokeGuardedCallback (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:4056:31)
      at beginWork$1 (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:23964:7)
      at performUnitOfWork (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:22779:12) Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
  See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
      at resolveDispatcher (/Users/USER_DIRECTORY/experimental/npm-workspaces/packages/package-b/node_modules/react/cjs/react.development.js:1476:13)
      at Object.useState (/Users/USER_DIRECTORY/experimental/npm-workspaces/packages/package-b/node_modules/react/cjs/react.development.js:1507:20)
      at App (/Users/USER_DIRECTORY/experimental/npm-workspaces/packages/package-b/src/components/App.tsx:10:29)
      at renderWithHooks (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:14985:18)
      at mountIndeterminateComponent (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:17811:13)
      at beginWork (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:19049:16)
      at HTMLUnknownElement.callCallback (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:3945:14)
      at HTMLUnknownElement.callTheUserObjectsOperation (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
      at invokeEventListeners (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
      at HTMLUnknownElementImpl._dispatch (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
      at HTMLUnknownElementImpl.dispatchEvent (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLUnknownElement.dispatchEvent (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
      at Object.invokeGuardedCallbackDev (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:3994:16)
      at invokeGuardedCallback (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:4056:31)
      at beginWork$1 (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:23964:7)
      at performUnitOfWork (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:22779:12)
      at workLoopSync (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:22707:5)
      at renderRootSync (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:22670:7)
      at performSyncWorkOnRoot (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:22293:18)
      at scheduleUpdateOnFiber (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:21881:7)
      at updateContainer (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:25482:3)
      at /Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:26021:7
      at unbatchedUpdates (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:22431:12)
      at legacyRenderSubtreeIntoContainer (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:26020:5)
      at Object.render (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:26103:10)
      at /Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/@testing-library/react/dist/pure.js:99:25
      at batchedUpdates$1 (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom.development.js:22380:12)
      at act (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
      at Object.render (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/@testing-library/react/dist/pure.js:95:26)
      at Object.<anonymous> (/Users/USER_DIRECTORY/experimental/npm-workspaces/packages/package-b/tests/components/App.test.tsx:5:29)
      at Object.asyncJestTest (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)
      at /Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jest-jasmine2/build/queueRunner.js:45:12
      at new Promise (<anonymous>)
      at mapper (/Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
      at /Users/USER_DIRECTORY/experimental/npm-workspaces/node_modules/jest-jasmine2/build/queueRunner.js:75:41
      at processTicksAndRejections (internal/process/task_queues.js:93:5)

  at VirtualConsole.<anonymous> (../../node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
  at reportException (../../node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:28)
  at innerInvokeEventListeners (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9)
  at invokeEventListeners (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
  at HTMLUnknownElementImpl._dispatch (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
  at HTMLUnknownElementImpl.dispatchEvent (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
  at HTMLUnknownElement.dispatchEvent (../../node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)

console.error
  The above error occurred in the <App> component:
  
      at App (/Users/USER_DIRECTORY/experimental/npm-workspaces/packages/package-b/src/components/App.tsx:10:29)
  
  Consider adding an error boundary to your tree to customize error handling behavior.
  Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

  at logCapturedError (../../node_modules/react-dom/cjs/react-dom.development.js:20085:23)
  at update.callback (../../node_modules/react-dom/cjs/react-dom.development.js:20118:5)
  at callCallback (../../node_modules/react-dom/cjs/react-dom.development.js:12318:12)
  at commitUpdateQueue (../../node_modules/react-dom/cjs/react-dom.development.js:12339:9)
  at commitLifeCycles (../../node_modules/react-dom/cjs/react-dom.development.js:20736:11)
  at commitLayoutEffects (../../node_modules/react-dom/cjs/react-dom.development.js:23426:7)
  at HTMLUnknownElement.callCallback (../../node_modules/react-dom/cjs/react-dom.development.js:3945:14)
  at HTMLUnknownElement.callTheUserObjectsOperation (../../node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)

● Testing render

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

   8 | export const App = (props: AppProps): JSX.Element => {
   9 |   // Create the count state.
> 10 |   const [count, setCount] = useState(0);
     |                             ^
  11 |   const [user, setUser] = useState<string>();
  12 |
  13 |   // Create the counter (+1 every second).

  at resolveDispatcher (node_modules/react/cjs/react.development.js:1476:13)
  at Object.useState (node_modules/react/cjs/react.development.js:1507:20)
  at App (src/components/App.tsx:10:29)
  at renderWithHooks (../../node_modules/react-dom/cjs/react-dom.development.js:14985:18)
  at mountIndeterminateComponent (../../node_modules/react-dom/cjs/react-dom.development.js:17811:13)
  at beginWork (../../node_modules/react-dom/cjs/react-dom.development.js:19049:16)
  at HTMLUnknownElement.callCallback (../../node_modules/react-dom/cjs/react-dom.development.js:3945:14)
  at HTMLUnknownElement.callTheUserObjectsOperation (../../node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
  at innerInvokeEventListeners (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
  at invokeEventListeners (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
  at HTMLUnknownElementImpl._dispatch (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
  at HTMLUnknownElementImpl.dispatchEvent (../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
  at HTMLUnknownElement.dispatchEvent (../../node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
  at Object.invokeGuardedCallbackDev (../../node_modules/react-dom/cjs/react-dom.development.js:3994:16)
  at invokeGuardedCallback (../../node_modules/react-dom/cjs/react-dom.development.js:4056:31)
  at beginWork$1 (../../node_modules/react-dom/cjs/react-dom.development.js:23964:7)
  at performUnitOfWork (../../node_modules/react-dom/cjs/react-dom.development.js:22779:12)
  at workLoopSync (../../node_modules/react-dom/cjs/react-dom.development.js:22707:5)
  at renderRootSync (../../node_modules/react-dom/cjs/react-dom.development.js:22670:7)
  at performSyncWorkOnRoot (../../node_modules/react-dom/cjs/react-dom.development.js:22293:18)
  at scheduleUpdateOnFiber (../../node_modules/react-dom/cjs/react-dom.development.js:21881:7)
  at updateContainer (../../node_modules/react-dom/cjs/react-dom.development.js:25482:3)
  at ../../node_modules/react-dom/cjs/react-dom.development.js:26021:7
  at unbatchedUpdates (../../node_modules/react-dom/cjs/react-dom.development.js:22431:12)
  at legacyRenderSubtreeIntoContainer (../../node_modules/react-dom/cjs/react-dom.development.js:26020:5)
  at Object.render (../../node_modules/react-dom/cjs/react-dom.development.js:26103:10)
  at ../../node_modules/@testing-library/react/dist/pure.js:99:25
  at batchedUpdates$1 (../../node_modules/react-dom/cjs/react-dom.development.js:22380:12)
  at act (../../node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
  at Object.render (../../node_modules/@testing-library/react/dist/pure.js:95:26)
  at Object.<anonymous> (tests/components/App.test.tsx:5:29)

So the @testing-library/react packages seems to be referencing the root level React versions, which cause an issue with the local versions.

Expected Behavior:

I expected the @testing-library/react to reference the workspace specific React versions.

Steps To Reproduce:

Package A package.json:
"dependencies": {
"react": "17.0.2",
"react-dom": "17.0.2",
},
"devDependencies": {
"@testing-library/react": "11.2.5",
"react-test-renderer": "17.0.2",
}

Package B package.json
"dependencies": {
"react": "17.0.1",
"react-dom": "17.0.1",
},
"devDependencies": {
"@testing-library/react": "11.2.5",
"react-test-renderer": "17.0.1",
}

And I created a very simple test for each package:

import { render } from '@testing-library/react';
import { App } from '../../src/components/App';

test('Testing render', () => {
const renderedElement = render();

expect(renderedElement).toBeDefined();

});

Environment:

OS: MacOS 11.2.3
Node: 14.15.4
npm: 7.7.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bugthing that needs fixingRelease 7.xwork is associated with a specific npm 7 release

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions