I have a Yarn workspace with two packages, watermelon-web
and watermelon-native
, which use the latest version of react-redux
but different versions of react
. The issue is that I am not able to control which version of react
Yarn chooses for the peerDependency of react-redux
.
Workspace package.json
:
{
"private": true,
"workspaces": {
"packages": [
"watermelon-web",
"watermelon-native"
],
"nohoist": [
"**/watermelon-native/react-redux"
]
}
}
(the nohoist is required to prevent a runtime error)
watermelon-web/package.json
:
{
"name": "watermelon-web",
"dependencies": {
"react": "^16.12.0",
"react-redux": "^7.1.3"
}
}
watermelon-native/package.json
:
{
"name": "watermelon-native",
"dependencies": {
"react": "16.8.3",
"react-redux": "^7.1.3"
}
}
Meanwhile, react-redux
has a peerDependency "react": "^16.8.3"
.
What I want to happen: After Yarn install, watermelon-native/node_modules/react-redux/node_modules
does NOT contain react
. This way, when, react-redux
tries to import react
at runtime, it would get [email protected]
from watermelon-native/node_modules
.
What actually happens: Yarn installs [email protected]
in watermelon-native/node_modules/react-redux/node_modules
. When I run watermelon-native
, React reports an "Invalid hook call" because watermelon-native
is using [email protected]
but react-redux
is using [email protected]
. (Both packages must be using the exact same instance of React for React hooks to work.)
How do I get Yarn to work the way I want it to?
I have tried using Yarn selective dependency resolutions, AKA the "resolutions" element in package.json
, in almost every way possible, but there was no observable change in Yarn's behavior. For example, I tried adding
"resolutions": {
"**/watermelon-native/react-redux/react": "16.8.3"
}
to the workspace package.json
.
Two easy "solutions" would be to use the same React version in all of my packages (would require downgrading watermelon-web
to 16.8.3
) or to forgo using Yarn workspaces. Each of these has drawbacks that I'd like to avoid if possible.
(Note: My code examples come from React Native development, but the question itself applies only to Yarn and has nothing to do with React. react
and react-redux
could be replaced by any other packages that have sufficiently similar dependencies.)
I think the answer to the question is just "Yarn doesn't work like that", for the time being at least.
In the meantime, I found a simple workaround. Since deleting the react
folder from watermelon-native/node_modules/react-redux/node_modules/react
fixes the issue, I added a postinstall
script that deletes that react
folder after every install.
My PowerShell script (use whatever shell you like)
function TryRemove-Path($path) {
if(Test-Path $path) {
Remove-Item -Recurse -Force $path
}
}
TryRemove-Path("$PSScriptRoot/node_modules/react-redux/node_modules/react")
This is pretty hacky, but even the Expo project relies on postinstall magic to get their React Native apps to work with yarn workspaces. So maybe this workaround is not so bad.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With