我有这个单线程,使用npm工作区构建:
├─ lib
│ └─ Foo
└─ src
├─ App
└─ Web
我想把Web
更新到React 18,而把App
留在React 17
当前(正在工作),我的依赖项是:
├─ lib
│ └─ Foo
├─ src
│ ├─ App
│ │ ├─ node_modules << no react
│ │ └─ package.json << no react
│ └─ Web
│ ├─ node_modules << no react
│ │ └─ next@18
│ └─ package.json << no react
├─ node_modules
│ ├─ bar@1 << peerDep: react ^17
│ ├─ react@17
│ └─ react-dom@17
└─ package.json << react & react-dom 17
在我尝试拆分版本之后,我的依赖项现在是:
├─ lib
│ └─ Foo
├─ src
│ ├─ App
│ │ ├─ node_modules << no react
│ │ └─ package.json << react & react-dom 17
│ └─ Web
│ ├─ node_modules
│ │ ├─ next@12
│ │ ├─ react@18
│ │ └─ react-dom@18
│ └─ package.json << react & react-dom 18
├─ node_modules
│ ├─ bar@2 << peerDep: react >=17
│ ├─ react@17
│ └─ react-dom@17
└─ package.json << no react
这就产生了以前最喜欢的:
Warning: 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.
TypeError: Cannot read properties of null (reading 'useState')
at useState (/src/web/node_modules/react/cjs/react.development.js:1620:21)
at AppContextProvider (webpack-internal:///./node_modules/bar/AppContextProvider/AppContextProvider.js:25:66)
at processChild (/node_modules/react-dom/cjs/react-dom-server.node.development.js:3043:14)
at resolve (/node_modules/react-dom/cjs/react-dom-server.node.development.js:2960:5)
at ReactDOMServerRenderer.render (/node_modules/react-dom/cjs/react-dom-server.node.development.js:3435:22)
at ReactDOMServerRenderer.read (/node_modules/react-dom/cjs/react-dom-server.node.development.js:3373:29)
at Object.renderToString (/node_modules/react-dom/cjs/react-dom-server.node.development.js:3988:27)
at Object.renderPage (/node_modules/next/dist/server/render.js:804:45)
at Object.defaultGetInitialProps (/node_modules/next/dist/server/render.js:391:51)
我认为是由./node_modules/react-dom@17
与./src/web/node_modules/react@18
冲突引起的
我想要达到的是可能的吗?
答案是使用overrides
,自npm 8.?.?
以来一直可用。我添加了问号,因为我不确定它是什么时候出现的,但它在版本8的早期迭代中不起作用。它当然适用于8.5.5
package.json
{
....
"overrides": {
"App": {
"react": "17.0.0"
},
"Web": {
"react": "18.0.0"
}
}
}
$ npm ls react
mono@1.0.0 /dev/mono
├─┬ app@0.0.1 -> ./app
│ └── react@17.0.0
├─┬ web@0.0.1 -> ./web
│ └── react@18.0.0
...
需要注意的一点是,这也会影响嵌套依赖项。您可以通过为每个受影响的依赖项广泛指定每个版本来扩展覆盖以保留其他版本,但到目前为止,我没有遇到任何问题,除了npm ls react
生成的重复警告,例如:
├─┬ @testing-library/react@12.1.5
│ ├─┬ react-dom@16.14.0
│ │ └── react@17.0.2 deduped invalid: "^16.14.0" from node_modules/react-dom
│ └── react@17.0.2 deduped