[ PROMPT_NODE_25286 ]
react-ui-patterns
[ SKILL_DOCUMENTATION ]
# React UI 模式
## 核心原则
1. **永不展示陈旧 UI** - 仅在真正加载时显示加载动画
2. **始终暴露错误** - 用户必须在出错时知情
3. **乐观更新** - 让 UI 感觉即时响应
4. **渐进式披露** - 内容可用时即显示
5. **优雅降级** - 部分数据优于无数据
## 加载状态模式
### 黄金法则
**仅在没有数据可显示时才显示加载指示器。**
typescript
// 正确 - 仅在无数据时显示加载
const { data, loading, error } = useGetItemsQuery();
if (error) return ;
if (loading && !data) return ;
if (!data?.items.length) return ;
return ;
typescript
// 错误 - 即使有缓存数据也会显示加载动画
if (loading) return ; // 重新获取时会闪烁!
### 加载状态决策树
是否有错误?
→ 是: 显示带重试选项的错误状态
→ 否: 继续
是否正在加载且没有数据?
→ 是: 显示加载指示器 (转圈/骨架屏)
→ 否: 继续
是否有数据?
→ 有数据: 显示数据
→ 有数据但为空: 显示空状态
→ 无: 显示加载 (兜底)
### 骨架屏 vs 加载转圈
| 使用骨架屏时 | 使用加载转圈时 |
|-------------------|------------------|
| 已知内容形状 | 未知内容形状 |
| 列表/卡片布局 | 模态框操作 |
| 初始页面加载 | 按钮提交 |
| 内容占位符 | 内联操作 |
## 错误处理模式
### 错误处理层级
1. 内联错误 (字段级) → 表单验证错误
2. Toast 通知 → 可恢复错误,用户可重试
3. 错误横幅 → 页面级错误,数据仍部分可用
4. 全屏错误页 → 不可恢复,需要用户干预
### 始终显示错误
**关键:绝不静默吞掉错误。**
typescript
// 正确 - 错误始终反馈给用户
const [createItem, { loading }] = useCreateItemMutation({
onCompleted: () => {
toast.success({ title: '项目已创建' });
},
onError: (error) => {
console.error('createItem 失败:', error);
toast.error({ title: '创建项目失败' });
},
});
// 错误 - 错误被静默捕获,用户一无所知
const [createItem] = useCreateItemMutation({
onError: (error) => {
console.error(error); // 用户什么也看不到!
},
});
### 错误状态组件模式
type