Claude Artifact 中 React 组件 prop 错误静默失败 —— 排查与修复

Claude 生成的 artifact 在预览面板里渲染成空白,没有任何控制台报错。本文教你怎么定位被沙箱吞掉的 React prop / import / hook 错误。

你让 Claude 写一个小的 React 组件 artifact —— 一个图表、一个表单、一组卡片。代码看上去没毛病,点 Preview,预览面板里一片空白。没有 loading,没有报错横幅,没有红色堆栈,什么都没有。滚动、改尺寸、点刷新,依然空白。切回 Code 视图,JSX 看着挺正常。你问 Claude “为什么空白?“,Claude 自信满满地把组件改写成一个略微不同的版本,继续空白。这种情况几乎都是沙箱吞掉了运行时报错 —— prop 类型不匹配、import 拿不到、没有 default export,或者 hydration 直接崩了,但沙箱接住后什么都不显示。

常见原因

按真实 artifact 调试中观察到的频率排序。

1. 组件期望一个 prop,但 artifact 宿主并没传

Claude 写了 export default function Card(&#123; title, items &#125;) &#123; ... &#125;,但调用时只写了 <Card />,没传 props。一到 items.map(...) 就在 undefined 上炸。沙箱接住,渲染成空。

如何识别:打开 Code 视图。找一下所有 props.something.mapprops.something.length、或者解构出来的 prop。如果父级调用没传那些,就是这个原因。

2. 缺 default export,或 named export 命名错

artifact 宿主导入的是顶层的 default export。如果 Claude 写的是 export function Component()、没有 default,宿主拿到的是 undefined,啥都不渲染。同理还有拼写错的 export defalut function

如何识别:在代码里搜索 export default,应该刚好有一处。如果只有 export function、没有任何 export default,就是它。

3. import 引了 artifact 运行时不支持的包

Claude 写了 import &#123; LineChart &#125; from 'recharts',但你账号 / 区域下的 artifact 运行时没把 recharts 加白名单。import 结果是 undefined,组件构造失败,沙箱渲染空白。

如何识别:看所有 import 行。artifact 运行时的白名单大致是:react、react-dom、lucide-react、recharts(有时)、shadcn/ui 原语。其他的都得怀疑。

4. JSX 语法错误被解析器吞了

Claude 生成的 JSX 里混入了一个游离的 <>。构建阶段解析失败,失败信息有时不在预览面板里高亮显示。

如何识别:找有没有非花括号包裹的 JSX 表达式,但里面又含 <>,比如写成了 <p>1 < 2</p> 而不是 <p>{'1 < 2'}</p>

5. hook 写在条件分支或 early return 之后

React 的 hooks 规则。如果 Claude 写了 if (!data) return null;,然后下面才 const [state, setState] = useState(...),下一次渲染时 hook 数量对不上,直接抛错。在 artifact 沙箱里这个抛错是静默的。

如何识别:从函数体顶部往下顺一遍。每个 useStateuseEffectuseMemo 在所有渲染路径上都要执行。任何一个被条件包裹,就是 bug。

6. Tailwind class 拼错,组件渲染出零尺寸

Claude 写了 class="w-0 h-0 ...",或者用了根本不存在的 Tailwind 工具类(比如 text-9.5xl),结果整个容器塌缩到 0。组件其实渲染了,只是看不见。

如何识别:在预览 iframe 上打开浏览器 DevTools(右键 → 检查元素)。如果 DOM 里有你的组件,但 width: 0 / height: 0,就是这个。

排查前的准备

  • 把空白预览面板和 Code 视图并排截图。
  • 记一下当前这次对话里,artifact 有没有曾经正确渲染过哪怕一次 —— 如果有,说明是后来某一轮被 Claude 改坏的。
  • 确认你用的是 Web 版 Claude 还是某个桌面壳子。桌面端的沙箱 CSP 有时比 Web 严。

需要收集的信息

  • artifact 的完整代码(从 Code 视图复制粘贴)。
  • 当前使用的 Claude 模型(Sonnet 4.6、Opus 4.7 等)。
  • 点 Preview 那一刻可能短暂闪过的错误文字(往往不到 1 秒就消失)。
  • artifact 顶部的所有 import 列表。
  • 你的账号套餐 —— 免费版的 artifact 库白名单更小。
  • 浏览器 DevTools 控制台输出(在点 Preview 之前就先打开)。

一步步修复

按 ROI 排序,便宜的检查在前。

第 1 步:点 Preview 之前先开 DevTools 控制台

这一步最关键:

1. 在 Claude 页面任意位置右键 → 检查。
2. 打开 Console 标签。
3. 勾上"保留日志"(Preserve log),防止报错被清掉。
4. 现在再点 artifact 的 Preview。

artifact 的 iframe 是沙箱,但报错确实会冒泡到父页面的控制台。你能看到真实的异常信息,通常是 TypeError: Cannot read properties of undefined (reading 'map')ReferenceError: SomePackage is not defined,直接告诉你要修哪。

第 2 步:让 Claude 套一个防御性包装层

一句 prompt 能修掉大多数 prop 相关的空白:

artifact 预览空白,且没有可见错误。请用 try/catch ErrorBoundary
把组件包起来,把捕获到的错误信息直接渲染到 UI 上。另外,给每一个
组件解构出的 prop 加上默认值。

Claude 会改写成 const &#123; title = 'Untitled', items = [] &#125; = props,再加上一个把错误显示出来的 ErrorBoundary

第 3 步:强制只保留一个 default export

让 Claude:

重构组件,在文件末尾保留唯一一个 default export:
export default ComponentName。删除其它所有 export。确认顶层
调用的标签名跟它对得上。

一句话搞定原因 #2。

第 4 步:把奇怪的 import 换成白名单内的

如果 import 列表里出现了 react / recharts / lucide-react / shadcn 之外的东西:

请只用以下库重写:react、recharts、lucide-react。如果需要一个
不在里面的 UI 原语,用 Tailwind 直接 inline 实现。

这能消掉原因 #3。

第 5 步:用一个已知能跑的最小模板兜底

把 artifact 重置到一个已知能跑的起点:

import React, { useState } from 'react';

export default function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold">Hello</h1>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  );
}

如果这个能跑,沙箱本身没问题,问题在 Claude 生成的代码。如果连这个都空白,沙箱坏了 —— 提工单。也可参考 Claude artifact 渲染空白

第 6 步:检查 DOM 里有没有零尺寸的元素

如果 DevTools 里能看到你的组件确实在 DOM 中,但预览视觉上空白:

1. DevTools → Elements 标签。
2. 找到你的顶层组件 div。
3. 看 Computed → width / height。
4. 如果是 0px,说明父容器塌缩了。要么显式加 minHeight,
   要么去掉冲突的 Tailwind class。

这能抓到原因 #6。

验证

  • 修完之后,在 DevTools 控制台打开的状态下再点一次 Preview。
  • 控制台不应有红色报错(key 相关的 warning 没关系)。
  • Elements 面板里组件可见,尺寸非 0。
  • 跟组件交互一下(点击、输入),操作不应该再触发新的错误。

长期预防

  • 给 Claude 生成的所有 prop 都加默认值:&#123; title = '', items = [] &#125;
  • 让 Claude 默认在每个 artifact 外面套一个 ErrorBoundary,把捕获到的错误显式渲染出来。
  • 留一份”已知能跑的最小模板”片段,从它开始迭代,比直接从复杂需求生成更稳。
  • 在 prompt 里钉死 artifact 依赖:“只用 react、recharts、lucide-react,别引其他库。”
  • 让 Claude 在现有 artifact 上迭代时,把当前代码贴回去 —— 否则它会从零重写,丢掉上下文。

常见坑

  • 把”预览空白”理解成”还没生成代码” —— 其实通常是”代码抛了,但没出现在 UI 上”。永远先看控制台。
  • 直接问 Claude “为什么空白”而不给它控制台报错 —— Claude 看不到 iframe 控制台,只能瞎猜。
  • 在一个坏掉的 artifact 上迭代 10 次。失败超过 3 次,就重置成最小模板,一步步往上加。
  • 以为在 Sonnet 上能跑的组件在 Opus 上一模一样能跑 —— 两个模型各自假定可用的库会有微妙差异。
  • 在 artifact 里用 dangerouslySetInnerHTML —— 沙箱有时会剥掉它,组件看着就是空。

FAQ

Q:控制台显示 “ChunkLoadError”,怎么办?

artifact 运行时想 lazy-load 一个 chunk 但失败了(网络或 CSP)。先强制刷新 Claude 页面。如果还是,说明你的 import 里某个库会触发被沙箱拦截的动态 import。换成可静态引入的替代品。

Q:同样的代码在 Claude 里能跑,我复制到自己的 React 项目就空白,为啥?

artifact 运行时自动注入了 React、有时候是 Tailwind,以及 shadcn 原语的 shim。你自己的项目得手动装并配上:npm install react react-dom recharts lucide-react,Tailwind 也要先配好。

Q:能看到 artifact 沙箱实际接住的错误文本吗?

可以 —— 在父页面的 DevTools 控制台里(见第 1 步)。沙箱吞掉了视觉上的错误横幅,但错误本身会冒泡到父窗口的 console。

Q:同一段 prompt,作者的 Claude 能跑,我的空白,为什么?

很可能是模型或套餐差异。免费版的 artifact 运行时白名单更紧。Pro / Team 版能 import 更多库。如果教程里能跑,先看下作者用的什么套餐。

相关阅读

标签: #排查 #Claude #artifacts #react #调试