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月前
|
人工智能 安全 网络虚拟化
为什么总显示请求超时或者一直运行中无反应,卸载重装了好几次,把各种安全软件和vpn等都关了也不行
该问题表现为AI工具频繁超时、卡在“生成中”无响应,强制停止无效甚至导致程序卡死。已尝试重装、关闭安全软件及VPN仍无效,疑似网络连接异常、服务端故障或本地环境兼容性问题。
|
3月前
|
人工智能 搜索推荐 测试技术
国家开始支持一人公司了,我做了一年的感想
深圳最高补贴 1000 万,OPC 写进政府工作报告。而我已经一个人做了快一年——没补贴没社区,用 AI 从零做了一个 SaaS。政策是好事,但真正的门槛不是工具,是持续执行力。
|
9天前
|
人工智能 资源调度 调度
AI时代,大学生应该提前准备什么?
AI时代,大学生面临就业重塑与能力升级的双重挑战。本文聚焦认知重构、三大核心能力(统筹力、技术力、实战力)及行动路径,倡导从“工具使用者”进阶为“AI决策者”,以T型+AI复合素养应对变革,在人机协同中抢占未来先机。
|
9天前
|
安全 人机交互 调度
《零基础搭建OpenClaw迁移训练环境指南》
智能体仿真完美、落地即崩的行业死结,根源从来不是仿真精度不足,而是传统Sim2Real始终困在视觉特征匹配的表层逻辑里。本文拆解OpenClaw颠覆性的虚实迁移方案,它彻底抛弃暴力域随机化的老路,构建了一套以跨感官因果认知为核心的迁移体系。通过阶梯式虚实过渡、动态经验权重调节、执行器在线自校准与虚实数据双向闭环,让智能体学习物理世界的本质规律而非表面特征。
115 6
|
9天前
|
人工智能 数据挖掘 BI
本体论 vs 语义层:两种 AI 业务语义底座的区别、场景与建设路径
本体论和语义层并不是互斥关系,也不是简单的“谁替代谁”。本体论表达了企业 AI 的高阶目标,语义层提供了多数企业更容易落地的起点。
|
9天前
|
NoSQL 数据可视化 网络安全
Another-Redis-Desktop-Manager.1.3.7安装步骤详解(附Redis可视化连接与Key管理教程)
Another-Redis-Desktop-Manager 1.3.7(ARDM)是一款轻量高效、开源免费的Redis可视化管理工具,支持单机/集群/哨兵模式,提供直观键值浏览、增删改查、命令控制台及中文界面,安装便捷,开箱即用。(239字)
|
2月前
|
机器学习/深度学习 搜索推荐 算法
拆解推荐系统:候选生成、过滤、排序、多样性的分层设计
推荐系统是端到端流水线,非单一算法:涵盖候选生成、过滤、特征工程、多目标排序、多样性调控与反馈闭环。强调关注点分离,以保障质量、速度与行为可控。动手前须明确定义Item、用户行为及成功指标。
436 12
拆解推荐系统:候选生成、过滤、排序、多样性的分层设计
|
2月前
|
存储 人工智能 JavaScript
Prompt、Context、Harness:AI Agent 工程的三层架构解析
2023年重“Prompt”(如何说),2025年重“Context”(看到什么),2026年跃升至“Harness”(系统级约束与验证)。三者非替代而是分层:Prompt优化表达,Context管理信息环境,Harness构建可信执行系统——模型是马,Harness才是缰绳、马鞍与路。
996 10
Prompt、Context、Harness:AI Agent 工程的三层架构解析
|
2月前
|
机器学习/深度学习 人工智能 运维
4类牛行为检测数据集(3600张)|YOLO训练数据集 智慧养殖 行为识别 健康监测 精准饲喂 牧场数字化管理
本数据集含3600张真实场景牛行为图像,精准标注4类关键行为(喝水、进食、卧下、站立),专为YOLO系列模型优化,支持智慧养殖、健康监测、精准饲喂与牧场数字化管理,开箱即用,助力农业AI落地。
|
1月前
|
人工智能 安全
深度测评:2026年中国医院精子SDF检测产品实测推荐
本文基于WHO标准与临床实测,从准确性、质控、报告维度及合规性四方面对比目前国内生殖中心常见的精子DFI检测四大品牌。结果显示:星博生物凭借AI纠错、双平台技术、全流程质控及首批二类证,综合表现最优,是精准评估男性生育力的首选。

热门文章

最新文章