[BUG] Workspaces hoisted package is not resolving to dependent's peer dependencies
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 10.1k
- Forks
- 4.7k
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 19
Description
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the failure with Jest in package-b and compare it with package-a, using packages/package-b/tests/components/App.test.tsx and packages/package-b/src/components/App.tsx. Trace which React and React DOM copies the test and @testing-library/react resolve. Done means package-b's test passes with its local React versions while the workspace's peer dependencies resolve correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nodejs, react, typescript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100