Monorepo自定义Hook报错:未找到react-redux上下文需包裹<Provider>
问题原因
这个报错不是你真的没在应用外层包裹<Provider>,核心原因是Lerna搭建的Monorepo架构下出现了react-redux多实例共存问题:
- 你存放Redux逻辑的独立子包,自己在node_modules里安装了一份单独的
react-redux依赖,和主应用里引入的react-redux是完全独立的两个实例 - 主应用里用的
<Provider>是主应用依赖的react-redux导出的,注入的上下文只对这份实例的Hooks生效;但你子包里封装的useSignInEffect调用的useSelector是子包自己那份react-redux导出的,读的是另一份独立的上下文,自然拿不到注入的store值,就会抛出找不到context的错误。
其他Redux功能正常是因为那些逻辑要么写在主应用里用的是主应用的react-redux实例,要么是直接调用store实例方法不依赖context,只有子包里导出的Hook用的是子包自己的react-redux,才会触发这个问题。
修复步骤
- 先确认多实例问题
在项目根目录执行命令检查依赖重复情况:
npm ls react-redux
如果输出结果里Redux子包的路径下单独挂载了一份react-redux,就可以确定是该问题导致。
- 调整子包依赖配置
打开Redux子包的package.json,把react、react-dom、react-redux这类要求全局单实例的依赖,从dependencies字段移动到peerDependencies,明确声明这些依赖由宿主应用提供,子包不单独打包安装:
{ "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0", "react-redux": ">=7.0.0" } }
如果子包本地开发、单元测试需要用到这些依赖,可以放到devDependencies里,不要放到生产依赖中。
顺便补全你自定义Hook里缺失的useEffect引入,这个问题会直接抛出引用错误,虽然不是本次context报错的诱因,但也需要修复:
import { useEffect } from 'react'; import { useSelector } from 'react-redux'; import type { EffectCallback } from 'react'; import type { RootState } from './your-store-type-path'; export const useSignInEffect = (effect: EffectCallback) => { const isSignedIn = useSelector((state: RootState) => state.auth.isSignedIn); useEffect(() => { if (isSignedIn) { return effect(); } }, [isSignedIn]); };
- 清理缓存重装依赖
在根目录执行命令删除所有残留依赖和锁文件,重新安装:
rm -rf node_modules packages/*/node_modules package-lock.json yarn.lock pnpm-lock.yaml npm install
- pnpm用户额外配置
如果你用pnpm作为Monorepo的包管理工具,还可以在根目录的.npmrc文件中添加如下配置,强制单实例依赖提升,避免多实例问题复现:
public-hoist-pattern[]=react public-hoist-pattern[]=react-dom public-hoist-pattern[]=react-redux
操作完成后重启开发服务,自定义Hook就能正常读取Provider注入的上下文,报错会消失。
内容的提问来源于stack exchange,提问作者cinemanja
相关产品推荐
相关产品推荐

