Learn why React Native projects break under pnpm’s default linking, and why switching to node-linker=hoisted is the simplest, most reliable fix in monorepos.Learn why React Native projects break under pnpm’s default linking, and why switching to node-linker=hoisted is the simplest, most reliable fix in monorepos.

The Real Fix for React Native + pnpm: Hoist Everything

2025/11/06 13:39
5 min read
For feedback or concerns regarding this content, please contact us at [email protected]

TL;DR

When working with React Native and pnpm, just use node-linker=hoisted instead of trying to selectively hoist individual packages. It will save you hours of debugging mysterious codegen errors and Kotlin compilation issues. (If you're in a monorepo, you'll also need to update build.gradle paths to point to the root node_modules.)

The Setup

I'm working on a React Native 0.82 project in a pnpm monorepo. The structure looks like this:

do-not-stop/ ├── mobile/ # React Native app ├── frontend/ # Web app ├── backend/ # API server ├── packages/ # Shared packages └── package.json # Root workspace

The Problem

During an Android build, I encountered this error:

Error: Cannot find module 'E:\git\do-not-stop\mobile\node_modules\@react-native\codegen\lib\cli\combine\combine-js-to-schema-cli.js'

The build was failing at the generateCodegenSchemaFromJavaScript task for @react-native-async-storage/async-storage. Classic React Native codegen issues.

The Initial "Solution" (That Didn't Work)

Following the conventional wisdom, I added the missing packages to mobile/package.json:

{ "dependencies": { "@react-native/codegen": "^0.82.1", "@react-native/gradle-plugin": "^0.82.1" } }

This seemed logical - the build needs these packages, so let's add them as dependencies. Right?

Wrong.

The Rabbit Hole Deepens

After adding these dependencies, I started getting Kotlin compilation errors:

Unresolved reference 'NativeRNWalletConnectModuleSpec' 'getName' overrides nothing 'getTypedExportedConstants' overrides nothing

The errors were coming from @walletconnect/react-native-compat, which was trying to use codegen-generated classes that weren't being found.

Attempting Selective Hoisting

I tried selective hoisting - first with a simple hoistPattern in package.json (which created even more issues with inconsistent paths and module resolution), then with a more sophisticated public-hoist-pattern configuration in .npmrc that others claim works. Here's the more comprehensive example:

# .npmrc # so gradle / metro can see my local package hoist-workspace-packages=true public-hoist-pattern[]=@myOrg/sharedPackage # so gradle and metro can see various cli tools and settings public-hoist-pattern[]=@react-native-community/* public-hoist-pattern[]=react-native public-hoist-pattern[]=@react-native/codegen public-hoist-pattern[]=@react-native/gradle-plugin public-hoist-pattern[]=@babel/runtime # i happen to be using this, and it has a complex native build step that didn't work without this hoist. # might be true for other packages that have native build steps public-hoist-pattern[]=react-native-gesture-handler

This configuration uses public-hoist-pattern (instead of hoistPattern in package.json) and includes workspace packages, a broader set of React Native packages, and packages with native build steps. But it still didn't work for me. This is exactly the problem with selective hoisting - even configurations that work for others can fail in your specific setup because:

  • React Native versions differ
  • Dependency trees vary based on your packages
  • Build tools evolve and change their expectations
  • Native modules have different requirements

If a configuration this comprehensive still fails, it's a clear sign that selective hoisting is fragile and outdated. The fact that it works for some but not others is precisely why full hoisting is the safer choice.

The Real Solution

After hours of debugging, I finally gave up on selective hoisting and went nuclear:

Added .npmrc at the root:

node-linker=hoisted

The hoisted linker ensures all packages are in a single node_modules directory, which React Native's build system expects.

For pnpm monorepos specifically, updated mobile/android/app/build.gradle to point to the root node_modules:

react { // Point to root node_modules since we're using hoisted linking in a monorepo reactNativeDir = file("../../../node_modules/react-native") codegenDir = file("../../../node_modules/@react-native/codegen") cliFile = file("../../../node_modules/react-native/cli.js") autolinkLibrariesWithApp() }

The paths go up three levels because:

  • mobile/android/app/build.gradlemobile/android/mobile/ → root

Note: If you're using pnpm with a standalone React Native project (not a monorepo), you only need the .npmrc change. The build.gradle modifications are only necessary when your React Native app is nested in a monorepo structure.

The Lesson

Selective hoisting in React Native projects using pnpm is a false optimization. You might think: "Couldn't I just track down all the React Native-related packages that need hoisting?" Technically, yes - you could spend hours finding @react-native/codegen, @react-native/gradle-plugin, @react-native/metro-config, @react-native/babel-preset, and all the other RN packages. But React Native's dependency structure changes frequently between versions. What works today might break tomorrow when you upgrade React Native or one of its tooling packages. You'd be playing whack-a-mole with your hoist patterns every time you update.

React Native's build system expects a certain structure. When you have Gradle looking for codegen, Metro bundler resolving modules, native code trying to import generated classes, and multiple tools working together, you need consistency, not clever path resolution. Hoisting everything gives you that consistency, and it's future-proof.

That said, if you really want to save disk space and are willing to maintain a selective hoisting configuration with pnpm's hoistPattern or public-hoist-pattern and symlinking strategies, it's technically possible. But this requires deep knowledge of React Native's dependency graph, ongoing maintenance as packages update, and potential debugging time when things break.

If you've successfully set up selective hoisting for React Native with pnpm and want to help others, please share your configuration in the comments! Include your .npmrc settings, package.json hoist patterns, and any build.gradle modifications you made.

Conclusion

Next time you're setting up a React Native project with pnpm, just hoist everything from the start. Your builds will be reliable, and your debugging time will be spent on actual features, not dependency resolution.


This article is part of the do-not-stop project - a full-stack Web3 playground with React Native mobile support.

Have you had similar experiences with React Native and pnpm? Share your horror stories (and solutions) in the comments!

Market Opportunity
RealLink Logo
RealLink Price(REAL)
$0.06225
$0.06225$0.06225
+0.90%
USD
RealLink (REAL) Live Price Chart
Disclaimer: The articles reposted on this site are sourced from public platforms and are provided for informational purposes only. They do not necessarily reflect the views of MEXC. All rights remain with the original authors. If you believe any content infringes on third-party rights, please contact [email protected] for removal. MEXC makes no guarantees regarding the accuracy, completeness, or timeliness of the content and is not responsible for any actions taken based on the information provided. The content does not constitute financial, legal, or other professional advice, nor should it be considered a recommendation or endorsement by MEXC.
Tags:

You May Also Like

And the Big Day Has Arrived: The Anticipated News for XRP and Dogecoin Tomorrow

And the Big Day Has Arrived: The Anticipated News for XRP and Dogecoin Tomorrow

The first-ever ETFs for XRP and Dogecoin are expected to launch in the US tomorrow. Here's what you need to know. Continue Reading: And the Big Day Has Arrived: The Anticipated News for XRP and Dogecoin Tomorrow
Share
Coinstats2025/09/18 04:33
Swiss Franc Intervention: Critical Analysis of SNB’s 2025 Policy and Safe-Haven Resilience

Swiss Franc Intervention: Critical Analysis of SNB’s 2025 Policy and Safe-Haven Resilience

BitcoinWorld Swiss Franc Intervention: Critical Analysis of SNB’s 2025 Policy and Safe-Haven Resilience ZURICH, March 2025 – The Swiss National Bank faces mounting
Share
bitcoinworld2026/03/16 23:10
Cashing In On University Patents Means Giving Up On Our Innovation Future

Cashing In On University Patents Means Giving Up On Our Innovation Future

The post Cashing In On University Patents Means Giving Up On Our Innovation Future appeared on BitcoinEthereumNews.com. “It’s a raid on American innovation that would deliver pennies to the Treasury while kneecapping the very engine of our economic and medical progress,” writes Pipes. Getty Images Washington is addicted to taxing success. Now, Commerce Secretary Howard Lutnick is floating a plan to skim half the patent earnings from inventions developed at universities with federal funding. It’s being sold as a way to shore up programs like Social Security. In reality, it’s a raid on American innovation that would deliver pennies to the Treasury while kneecapping the very engine of our economic and medical progress. Yes, taxpayer dollars support early-stage research. But the real payoff comes later—in the jobs created, cures discovered, and industries launched when universities and private industry turn those discoveries into real products. By comparison, the sums at stake in patent licensing are trivial. Universities collectively earn only about $3.6 billion annually in patent income—less than the federal government spends on Social Security in a single day. Even confiscating half would barely register against a $6 trillion federal budget. And yet the damage from such a policy would be anything but trivial. The true return on taxpayer investment isn’t in licensing checks sent to Washington, but in the downstream economic activity that federally supported research unleashes. Thanks to the bipartisan Bayh-Dole Act of 1980, universities and private industry have powerful incentives to translate early-stage discoveries into real-world products. Before Bayh-Dole, the government hoarded patents from federally funded research, and fewer than 5% were ever licensed. Once universities could own and license their own inventions, innovation exploded. The result has been one of the best returns on investment in government history. Since 1996, university research has added nearly $2 trillion to U.S. industrial output, supported 6.5 million jobs, and launched more than 19,000 startups. Those companies pay…
Share
BitcoinEthereumNews2025/09/18 03:26