Yarn 3 Monorepo中UI包调用AsyncStorage.setItem报undefined错误
React Native Yarn 3 Monorepo UI包调用AsyncStorage报错解决指南
问题说明
用Yarn 3搭建的React Native monorepo项目,包含主App工程rnapp和一个独立UI包。UI包内的ThemeProvider组件调用@react-native-async-storage/async-storage的setItem方法时,主App引入该UI包会触发以下错误:
[TypeError: Cannot read property 'setItem' of undefined]
已确认主App和UI包均安装该依赖,主App直接调用setItem正常,仅通过UI包调用时出错。
问题根源
- 原生模块解析缺失:AsyncStorage属于原生模块,Metro默认未对monorepo子包做完整的原生依赖解析,导致UI包无法获取正确的模块实例
- 依赖隔离/重复实例:Yarn 3的依赖隔离机制可能让UI包与主App的AsyncStorage实例不共享,或版本不一致引发冲突
解决步骤
1. 统一依赖配置,避免重复安装
- 在根目录
package.json中,将@react-native-async-storage/async-storage声明为工作区共享依赖:
{ "workspaces": { "packages": ["rnapp", "packages/ui"], "dependencies": { "@react-native-async-storage/async-storage": "^1.19.0" } } }
- 在UI包的
package.json中,将该依赖移至peerDependencies,复用主App的依赖实例:
{ "peerDependencies": { "@react-native-async-storage/async-storage": "^1.19.0" } }
- 执行
yarn install更新依赖
2. 修改Metro配置,支持子包解析
编辑主App的metro.config.js,让Metro识别工作区中的UI包:
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const path = require('path'); module.exports = mergeConfig(getDefaultConfig(__dirname), { resolver: { extraNodeModules: { // 替换为你的UI包实际名称 "your-ui-package-name": path.resolve(__dirname, "../packages/ui") } }, watchFolders: [ path.resolve(__dirname, "../packages/ui") ] });
3. 规范UI包的导入方式
UI包必须使用标准导入语法,禁止使用相对路径或非官方导入:
import AsyncStorage from '@react-native-async-storage/async-storage'; // ThemeProvider中的使用示例 const saveTheme = async (themeValue) => { try { await AsyncStorage.setItem('app-theme', themeValue); } catch (err) { console.error('存储主题失败:', err); } };
4. 清除缓存并重建项目
执行以下命令彻底清除缓存,避免旧缓存干扰:
# 清除Metro缓存 npx metro-cache clean # 进入主App目录清除React Native缓存 cd rnapp && npx react-native clean # 重新构建项目(根据平台选择) cd rnapp && npx react-native run-android # iOS环境用run-ios
验证方法
- 在UI包的
ThemeProvider中添加测试代码,调用AsyncStorage.getItem验证模块实例是否正常 - 主App引入UI包后运行项目,检查是否仍出现报错
- 执行
yarn why @react-native-async-storage/async-storage查看依赖树,确认该依赖仅存在一个实例
内容的提问来源于stack exchange,提问作者themaster
相关产品推荐
相关产品推荐

