react-native-builder-bob icon indicating copy to clipboard operation
react-native-builder-bob copied to clipboard

fix(template): disable hierarchical lookup in Metro config to fix mod…

Open jkrmarmol opened this issue 6 months ago • 4 comments

Summary

While working with a JavaScript Library module generated using create-react-native-library, I encountered module resolution issues when integrating the library into an Expo-managed project. React components and other dependencies failed to load correctly, which was caused by Metro’s default hierarchical lookup behavior.

Upon reviewing the generated metro.config.js, I found that it did not explicitly disable hierarchical lookup. This was resolved by adding the following line:

config.resolver.disableHierarchicalLookup = true;

Error Encountered Without This Fix

When disableHierarchicalLookup is not set to true, the app throws this error at runtime:

image

This error typically indicates duplicate React instances or improper module resolution, both symptoms of Metro resolving dependencies from unexpected directories due to hierarchical lookup.

Rationale

By default, Metro traverses parent directories when resolving modules, which can lead to:

  • React components not loading
  • Duplicate or conflicting dependency versions
  • Unexpected module resolution behavior in monorepo or workspace environments

This is especially problematic when using Expo or working in monorepos, as described in the Expo Monorepo Guide (Step 3). To avoid this, Expo recommends explicitly setting disableHierarchicalLookup to true to ensure Metro resolves modules only from the expected local node_modules path.

Affected File

This update applies to the metro.config.js generated when selecting:

? What type of library do you want to develop? › JavaScript Library

Testing

To verify the fix:

  1. Run the CLI command to create a new module:
    packages\create-react-native-library\bin\create-react-native-library.cmd
    
  2. Select JavaScript Library as the module type.
  3. After generation, open the file at example/metro.config.js.
  4. Confirm that the line
    config.resolver.disableHierarchicalLookup = true;
    
    has been added.

This confirms that the updated configuration is correctly included in the generated example project.

jkrmarmol avatar May 21 '25 14:05 jkrmarmol

Thanks for the PR. Can you provide more details on the exact issue you faced and share a repo that reproduces the issue?

Our config should already prevent importing multiple versions of React by blocking duplicate versions of packages defined in peer dependency. If this is not working correctly, I want to identify the bug in the blocking mechanism, and fix that. I'd prefer to keep Metro's resolution mechanism behavior similar to Node.js to avoid inconsistencies with other tools in the project.

satya164 avatar May 21 '25 18:05 satya164

Thanks for the PR. Can you provide more details on the exact issue you faced and share a repo that reproduces the issue?

Our config should already prevent importing multiple versions of React by blocking duplicate versions of packages defined in peer dependency. If this is not working correctly, I want to identify the bug in the blocking mechanism, and fix that. I'd prefer to keep Metro's resolution mechanism behavior similar to Node.js to avoid inconsistencies with other tools in the project.

I’ve created a minimal reproduction repository here

Steps to reproduce the issue:

  1. Clone the repo and run the example app (yarn && yarn example start).
  2. You'll see the following issue: image

jkrmarmol avatar May 22 '25 03:05 jkrmarmol

Hey @jkrmarmol, I tested your repro but don't get this error.

CleanShot 2025-05-22 at 23 55 11@2x

Can you share info about your environment?

  • Node version
  • Platform you're testing on

satya164 avatar May 22 '25 21:05 satya164

I'm currently using Windows 11 as my OS.

Node version: v22.13.1 Platform: Android Expo Go OS: Windows 11

jkrmarmol avatar May 23 '25 02:05 jkrmarmol

Hey @jkrmarmol, I tested your repro but don't get this error.

CleanShot 2025-05-22 at 23 55 11@2x

Can you share info about your environment?

  • Node version
  • Platform you're testing on

I think this is a compatibility issue. I created a clean example using the CLI (not using Expo), and I can reproduce the same error when building on Windows. However, the build works fine on macOS.

vinova-vito avatar Jul 22 '25 08:07 vinova-vito

I was getting same Invalid hook call because of having duplicate react instances After applying config.resolver.disableHierarchicalLookup = true; to fix it, I'm getting this:

 Error: Unable to resolve module @babel/runtime/helpers/interopRequireDefault from E:\coding\reactnative\@cafebazaar\react-native-poolakey\example\index.js: @babel/runtime/helpers/interopRequireDefault could not be found within the project.
> 1 | import { AppRegistry } from 'react-native';
  2 | import App from './src/App';
  3 | import { name as appName } from './app.json';

masarbazi avatar Sep 25 '25 05:09 masarbazi

The problem of duplicate react instance comes from root package.json misconfigured dependencies. The react and react-native should be listed under peerDepedencies field, not installed as independent dependencies. So in your shared repo lines this and this should be deleted. The project template created with create-react-native-library is wrong in couple of places which I will create an issue for that.

masarbazi avatar Sep 26 '25 20:09 masarbazi