React Native如何访问根目录外的文件/目录(Monorepo场景)
React Native Monorepo 访问外部共享屏幕目录时的Invalid Hook Call错误修复
场景说明
采用Monorepo结构开发跨端项目,目录如下:
Monorepo ├── App(React Native项目) ├── Web(Next.js项目) └── Screen(存放共享屏幕组件)
配置metro.config.js和babel.config.js尝试访问Screen目录后,出现错误:
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component.
错误原因
该错误本质是React/React Native包被重复加载:共享的Screen目录没有独立的依赖管理,RN App和Screen目录会解析到不同的React实例,导致Hook调用时的校验逻辑失败。
修复步骤
1. 调整Metro配置(metro.config.js)
确保Metro只从RN App的node_modules加载依赖,同时正确映射共享目录:
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const path = require('path'); const config = { // 监听共享目录,确保文件变更能被Metro检测到 watchFolders: [path.resolve(__dirname, '../Screen')], resolver: { // 强制RN仅使用自身目录下的node_modules,避免加载根目录或其他子项目的依赖 nodeModulesPaths: [path.resolve(__dirname, 'node_modules')], // 统一别名,和Babel配置保持一致 alias: { '@screen': path.resolve(__dirname, '../Screen'), }, }, }; module.exports = mergeConfig(getDefaultConfig(__dirname), config);
2. 修正Babel配置(babel.config.js)
调整module-resolver的根路径,避免向上查找导致的依赖重复:
module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: [ 'react-native-reanimated/plugin', [ 'module-resolver', { // 以RN App目录为根路径,限制依赖查找范围 root: ['./'], alias: { '@screen': '../Screen', }, // 明确支持的文件扩展名,避免解析歧义 extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], }, ], ], };
3. 规范共享目录的依赖管理
如果Screen目录有自己的package.json,需将React相关依赖设为peerDependencies,避免安装重复包:
{ "name": "@your-project/screen", "peerDependencies": { "react": "*", "react-native": "*" } }
如果没有独立的package.json,直接删除该目录下的node_modules(如果存在)。
4. 清除缓存并重启服务
执行以下命令清除Metro缓存,然后重启RN应用:
npx react-native start --reset-cache
内容的提问来源于stack exchange,提问作者Ashish Devashi
相关产品推荐
相关产品推荐

