Day6的一个tips:Electron在Monorepo React 渲染错误排查:从 Hook 崩溃到根治

简介: 记录 Monorepo 中 Web 与 Electron 端 React "Invalid hook call" 的完整排查过程,涵盖版本错配、实例混用、CSP 拦截等根因分析与修复方案。

渲染层报错复盘(Web + Electron)

1. 背景

在完成 Zustand Store 迁移后,webdesktop(electron renderer) 先后出现 React 渲染错误,主要表现为:

  • Invalid hook call
  • Cannot read properties of null (reading 'useRef' / 'useState')
  • Incompatible React versions

这些错误会导致页面无法渲染,属于高优先级阻塞问题。


2. 问题现象

2.1 Web 端

关键报错:

  • Invalid hook call. Hooks can only be called inside of the body of a function component.
  • 触发点:<BrowserRouter>main.tsx:9
  • 连带报错:Cannot read properties of null (reading 'useRef')

2.2 Web 端二次报错(修复过程中的中间态)

关键报错:

  • Incompatible React versions
  • react: 19.1.0
  • react-dom: 19.2.5

说明渲染时拿到的 reactreact-dom 不是同一版本。

2.3 Electron 渲染进程

关键报错:

  • Invalid hook call
  • Cannot read properties of null (reading 'useState')
  • 触发组件:Versions.tsx

3. 根因分析

根因 A:Monorepo 下 React 实例混用

在 workspace 场景下,不同 app 的 reactreact-dom 解析路径可能不同,导致:

  • 业务代码使用了一份 react
  • 渲染器(react-dom / router)使用了另一份 react

从而触发 Invalid hook call

根因 B:一次错误修复带来的版本错配

为修复 Web 端 Invalid hook call,曾尝试在 Vite 中把 react alias 到 workspace 根。随后发现根目录实际版本为:

  • root react = 19.1.0
  • root react-dom = 19.2.5

这会直接触发 Incompatible React versions

根因 C:Electron 渲染端依赖归类导致运行时解析不稳定

apps/desktop 初始将 reactreact-dom 放在 devDependencies,配合 monorepo hoist 后,渲染进程更容易解析到非预期位置的包。


4. 排查路径(实际执行)

  1. 定位异常入口:

    • apps/web/src/main.tsx<BrowserRouter>
    • apps/desktop/src/renderer/src/components/Versions.tsx
  2. 检查版本与依赖树:

    • pnpm --filter @aitodos/web why react
    • pnpm --filter @aitodos/store why react
    • pnpm --filter desktop why react
  3. 检查运行时解析路径(关键):

    • require.resolve('react')
    • require.resolve('react-dom')
    • 分别在 apps/webapps/adminapps/desktop 目录执行
  4. 检查本地安装版本:

    • node_modules/react/package.json
    • node_modules/react-dom/package.json

5. 修复动作(按时间顺序)

5.1 Web/Admin 首轮修复

文件:

  • apps/web/vite.config.ts
  • apps/admin/vite.config.ts

动作:

  • 增加 resolve.dedupe: ['react', 'react-dom']

作用:

  • 降低同一应用加载多份 React 的风险。

5.2 修复过程中的错误动作(已回滚)

动作:

  • 在 Web/Admin Vite 里把 react/react-dom alias 到 workspace 根

结果:

  • 命中了 root react=19.1.0react-dom=19.2.5 的版本错配
  • 出现 Incompatible React versions

处理:

  • 回滚该 alias,仅保留 dedupe

5.3 Electron Renderer 修复

文件:

  • apps/desktop/electron.vite.config.ts
  • apps/desktop/package.json

动作 1(解析一致化):

  • renderer.resolve 中保留 dedupe: ['react', 'react-dom']
  • 显式增加:react: resolve('node_modules/react')

动作 2(依赖归类修正):

  • reactreact-domdevDependencies 移到 dependencies

目的:

  • 保证 Electron 渲染进程运行时拿到同一套 React 运行时依赖。

5.4 依赖重装与重启

执行:

pnpm install --filter desktop
pnpm --filter desktop dev

结果:

  • 安装成功(exit code 0)
  • Electron renderer dev server 启动成功

6. 最终状态

  • Web 端渲染恢复正常
  • Electron 渲染进程可启动并进入页面
  • Invalid hook call 链路已完成定向修复

7. 可复用修复模板

当再次出现 Invalid hook call 时,建议按以下顺序:

  1. 先查“版本一致性”

    • reactreact-dom 必须完全同版本
  2. 再查“解析路径一致性”

    • 比较 require.resolve('react')require.resolve('react-dom')
  3. 在 bundler 中启用去重

    • resolve.dedupe: ['react', 'react-dom']
  4. 对 Electron/运行时 app,确保 React 是运行时依赖

    • 放在 dependencies 而非仅 devDependencies
  5. 每次改完配置必须重启进程

    • 停掉旧的 dev 进程
    • 重新启动并强刷页面

8. 备注

  • apps/desktoppnpm.onlyBuiltDependencies 配置警告属于配置位置提示,不是本次渲染错误根因。
  • 若后续仍偶发异常,优先加运行时日志打印 React 解析路径和版本再定位。

9. 补充:Electron 复用 Web 后样式丢失与 CSP 报错

9.1 问题现象 A:页面“有结构、无样式”

现象:

  • Electron 页面能渲染文本和结构,但 Tailwind 视觉样式几乎全部失效。
  • 页面看起来像纯 HTML 默认样式。

关联报错(阶段性):

  • [plugin:vite:import-analysis] Failed to resolve import "@web/index.css"

根因:

  1. main.tsx 直接从 @web/index.css 引入时,CSS alias 在 Electron + Vite 场景下解析不稳定。
  2. apps/desktop 原模板样式文件未显式扫描 apps/web/src,导致 Tailwind 未生成 Web 页面实际使用的 utility class。

修复:

  • apps/desktop/src/renderer/src/main.tsx
    • 使用 desktop 本地样式入口:import './assets/main.css'
  • apps/desktop/src/renderer/src/assets/main.css
    • 保留 @import "tailwindcss";
    • 增加扫描源:
      • @source "../../../../../web/src/**/*.{ts,tsx}";
      • @source "../**/*.{ts,tsx}";
    • 移除 Electron 模板页遗留样式,保留通用基础规则(html/body/#root)。

验证:

  • pnpm --filter desktop build 通过。
  • 构建后的 renderer CSS 体积明显增大(说明 Tailwind utility 已成功生成)。

9.2 问题现象 B:CSP 拒绝 unsafe-eval

关键报错:

  • Uncaught EvalError: Evaluating a string as JavaScript violates CSP ... 'unsafe-eval'
  • 触发点:packages/shared/src/storage.ts

根因:

  • 为了条件加载 Taro/RN 存储实现,代码中使用了 new Function(...) 进行动态导入;
  • Electron 渲染进程默认 CSP 不允许 unsafe-eval,因此直接报错。

修复:

  • packages/shared/src/storage.ts
    • new Function(...) 改为 CSP 安全写法:
      • import(/* @vite-ignore */ modulePath)

验证:

  • pnpm --filter @aitodos/shared type-check 通过。
  • pnpm --filter desktop typecheck 通过。
  • Electron 运行时不再出现 unsafe-eval 相关异常。

9.3 结论

  • 复用 Web 到 Electron 时,样式链路要以 desktop 为入口统一管理;
  • Tailwind v4 需要在 desktop 的 CSS 入口显式声明 @source 扫描 Web 源码;
  • 渲染层共享代码必须避免 eval/new Function,否则容易被 CSP 拦截。
相关文章
|
1月前
|
机器学习/深度学习 搜索推荐 算法
拆解推荐系统:候选生成、过滤、排序、多样性的分层设计
推荐系统是端到端流水线,非单一算法:涵盖候选生成、过滤、特征工程、多目标排序、多样性调控与反馈闭环。强调关注点分离,以保障质量、速度与行为可控。动手前须明确定义Item、用户行为及成功指标。
349 12
拆解推荐系统:候选生成、过滤、排序、多样性的分层设计
|
1月前
|
人工智能 机器人 网络安全
使用 Lume 在 macOS 虚拟机中隔离运行 OpenClaw/Moltbot:完整部署指南
OpenClaw(龙虾)是开源本地AI智能体,可7×24小时在你设备上自主执行任务。支持微信/飞书/Telegram等50+渠道,具备持久记忆、网页浏览、文件操作与自我扩展能力,数据全留本地,隐私可控。(239字)
494 7
使用 Lume 在 macOS 虚拟机中隔离运行 OpenClaw/Moltbot:完整部署指南
|
1月前
|
机器学习/深度学习 人工智能 运维
4类牛行为检测数据集(3600张)|YOLO训练数据集 智慧养殖 行为识别 健康监测 精准饲喂 牧场数字化管理
本数据集含3600张真实场景牛行为图像,精准标注4类关键行为(喝水、进食、卧下、站立),专为YOLO系列模型优化,支持智慧养殖、健康监测、精准饲喂与牧场数字化管理,开箱即用,助力农业AI落地。
|
1月前
|
存储 弹性计算 监控
阿里云云服务器ECS实例介绍及选择建议
阿里云ECS是安全可靠、弹性伸缩的云服务器服务,提供通用型、计算型、内存型等8类实例,适配Web、数据库、AI、大数据等场景。支持免费试用,兼顾性能与成本,助力企业降本增效。
409 13
|
2月前
|
Java 数据库 数据格式
【Spring注解】Spring生态常见注解——面试高频考点总结
本文系统梳理Spring生态高频面试注解考点,直击本质——注解只是表象,核心考察IOC容器、Bean生命周期、MVC流程、AOP代理、自动配置与事务机制等底层原理。涵盖@Component/@Configuration、@Autowired/@Resource、@RestController、@Transactional、@SpringBootApplication、@RequestBody等七大类注解的辨析、原理、坑点 及 TOP10 必背题。
433 12
|
1月前
|
存储 人工智能 JavaScript
Prompt、Context、Harness:AI Agent 工程的三层架构解析
2023年重“Prompt”(如何说),2025年重“Context”(看到什么),2026年跃升至“Harness”(系统级约束与验证)。三者非替代而是分层:Prompt优化表达,Context管理信息环境,Harness构建可信执行系统——模型是马,Harness才是缰绳、马鞍与路。
745 10
Prompt、Context、Harness:AI Agent 工程的三层架构解析
|
18天前
|
人工智能 安全
深度测评:2026年中国医院精子SDF检测产品实测推荐
本文基于WHO标准与临床实测,从准确性、质控、报告维度及合规性四方面对比目前国内生殖中心常见的精子DFI检测四大品牌。结果显示:星博生物凭借AI纠错、双平台技术、全流程质控及首批二类证,综合表现最优,是精准评估男性生育力的首选。
|
15天前
|
存储 弹性计算 人工智能
使用更少的钱购买到阿里云服务器的方法,亲测省钱购买阿里云指南
阿里云省钱购机指南:学生可领300元无门槛代金券,个人/企业用户享折扣券+代金券;推荐抢购38元/年轻量服务器、99元/年ECS等特惠机型,阿里云官方活动:https://t.aliyun.com/U/OTnSAH 并通过活动中心、权益中心及高校计划叠加优惠,大幅降低上云成本。
|
19天前
|
人工智能 缓存 前端开发
Day4-5:Web 双端适配与 Admin 系统全栈落地实录
本文档整合了 Day 4 与 Day 5 的开发进展,核心涵盖 Web 端响应式 UI 复现、云端资讯 API 接入,以及 Admin 管理系统的架构设计与模块化开发步骤,打通了从用户体验到后台管理的完整链路。
|
21天前
|
人工智能 缓存 前端开发
从 0 到 1:AI Todos 项目 Day1 实战——用 pnpm + Turbo 搭建可迭代的 Monorepo 基线
记录AI待办(AiTodos)Monorepo项目的首日基础工程搭建全过程,涵盖pnpm工作区配置、目录骨架初始化、Turbo任务编排、TypeScript统一配置、Vite/Fastify应用初始化、跨包共享(shared/api-sdk/store)及标准化脚本建设,完成可运行、可检查、可扩展的现代化前端工程基线。

热门文章

最新文章