fix: 消除文章页 dev 下的 "Invalid hook call" 告警
现象
dev 下每次打开文章页,终端都会打印 2 次 React 的 "Invalid hook call"。
生产构建没有;首页、/thoughts/、/friends/ 也没有。
根因(用临时 Vite 插件抓的调用栈定位)
不是 React 多副本,也不是 hooks 写法有问题,而是 Astro 的渲染器探测:
1. TableOfContents 首屏 headings 为空 → `return null`(数据在 useEffect 里填,
SSR 期不执行)
2. @astrojs/react 的 check 会试渲染一次,拿到 null 就认不出这是 React 组件 → false
3. Astro 转向下一个渲染器 @astrojs/mdx
4. MDX 的 check 把组件**当普通函数裸调** `await Component({...})`,不在 React
渲染树里 → useState 找不到 dispatcher → 报 Invalid hook call → 抛错被 catch
5. 两个渲染器都说不是自己的,Astro 最终仍用 React 正确渲染了组件
所以页面和组件一直是对的,只有日志是错的。生产构建没有是因为 React 生产版
剥掉了这段 dev-only 警告(栈里是 react.development.js)。
Hero 之类的组件不报,是因为它们探测时返回真实 JSX,第 2 步就被 React 认出来了。
修法
去掉 `if (headings.length === 0) return null`,改为始终返回 <nav>,无标题时用
`hidden` 收起,视觉结果不变。这样第 2 步就能认出是 React 组件,根本不会走到
MDX 的探测。代价是文章页 SSR 多出 2 个 display:none 的空 <nav>(两个 TOC 实例各一个),
以及 island 上多了 Astro 的 await-children 标记。
另一条路(未采用):项目里 0 个 .mdx,直接删掉 @astrojs/mdx 也能消除告警,
且零 DOM 变化。选择保留 MDX 是为了不因一个纯噪音的警告砍掉一个能力。
验证
dev 下逐个请求 5 类页面(含之前必现的 2 个文章页)告警数全为 0;
生产构建与基线的差异只剩本次有意的隐藏 nav、资源哈希和 island uid;
pnpm build 41 页 + pagefind 通过;astro check 仍是 1 error/0 warnings(原有报错)。
This commit is contained in:
@@ -285,10 +285,20 @@ export function TableOfContents({ showHeader = true }: TableOfContentsProps) {
|
||||
}, 2500)
|
||||
}
|
||||
|
||||
if (headings.length === 0) return null
|
||||
|
||||
// 注意:这里不能 `return null`。
|
||||
//
|
||||
// Astro 靠「渲染器探测」决定交给哪个框架渲染:@astrojs/react 的 check 会试渲染一次,
|
||||
// 拿到 null 就认不出这是 React 组件;接着轮到 @astrojs/mdx 的 check,而它是把组件
|
||||
// 当普通函数**裸调**(不在 React 渲染树里),useState 找不到 dispatcher,于是每次
|
||||
// SSR 都往控制台打一条 "Invalid hook call"。页面本身没错,但那行日志很误导人。
|
||||
//
|
||||
// 始终返回 <nav>,没有标题时用 hidden 收起来 —— 视觉结果和 return null 一样。
|
||||
return (
|
||||
<nav ref={navRef} aria-label="目录" className="toc-nav">
|
||||
<nav
|
||||
ref={navRef}
|
||||
aria-label="目录"
|
||||
className={cn("toc-nav", headings.length === 0 && "hidden")}
|
||||
>
|
||||
{showHeader ? (
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<div className="w-1 h-4 bg-primary rounded-full" />
|
||||
|
||||
Reference in New Issue
Block a user