React开发避坑指南Skill pitfalls-react

React 开发避坑指南,提供 React 组件模式、表单验证、错误边界、可访问性 (a11y) 和响应式设计的常见陷阱与最佳实践。适用于前端开发、代码审查、性能优化、用户体验提升。关键词:React 组件,表单验证,错误边界,可访问性,响应式设计,前端开发,React Hook Form,Zod,ARIA,useEffect。

前端开发 0 次安装 0 次浏览 更新于 3/2/2026

name: pitfalls-react description: “React组件模式、表单、可访问性和响应式设计。在构建React组件、处理表单或确保可访问性时使用。触发条件:React组件、useEffect、表单验证、a11y、响应式、错误边界。”

React 常见陷阱

React 开发中的常见陷阱与正确模式。

何时使用

  • 构建 React 组件
  • 实现表单验证
  • 添加错误边界
  • 确保可访问性 (a11y)
  • 创建响应式布局
  • 审查 React 代码

工作流程

步骤 1:检查组件模式

验证加载/错误状态和数据检查。

步骤 2:验证表单验证

确保使用 Zod 模式并正确显示错误。

步骤 3:检查可访问性

验证 ARIA 标签和键盘导航。


组件模式

// ✅ 在使用前定义辅助函数或将其导出
function formatPrice(price: number) { ... }

export default function Component() {
  // ✅ 在访问前检查数据是否存在
  if (!data) return <Loading />;

  // ✅ useEffect 仅用于副作用
  useEffect(() => {
    fetchData();
  }, []);

  // ✅ 在交互元素上使用 data-testid
  return <button data-testid="submit-btn">提交</button>;
}

// ❌ 错误:在渲染中定义函数
return <button onClick={() => {
  function doSomething() { } // 不要在这里定义
  doSomething();
}}>

// ✅ 使用路由器导航,而非 window
import { Link, useLocation } from 'wouter';
<Link to="/dashboard">前往</Link>
// ❌ window.location.href = '/dashboard'

错误边界

// ✅ 将主要组件包裹在错误边界中
class ErrorBoundary extends React.Component {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, info) {
    logError({ error, componentStack: info.componentStack });
  }

  render() {
    if (this.state.hasError) {
      return <ErrorFallback onRetry={() => this.setState({ hasError: false })} />;
    }
    return this.props.children;
  }
}

// ✅ 优雅降级
function Dashboard() {
  const { data, error, isLoading } = useQuery(...);

  if (isLoading) return <Skeleton />;
  if (error) return <ErrorCard message="无法加载" onRetry={refetch} />;
  if (!data) return <EmptyState />;

  return <DashboardContent data={data} />;
}

表单验证

// ✅ 为所有表单使用 Zod 模式
const createStrategySchema = z.object({
  name: z.string().min(1, '名称必填').max(100),
  type: z.enum(['cross-exchange', 'triangular']),
  minProfit: z.number().positive('必须为正数'),
});

// ✅ 将 React Hook Form 与 Zod 结合使用
const form = useForm<z.infer<typeof createStrategySchema>>({
  resolver: zodResolver(createStrategySchema),
});

// ✅ 内联显示错误
{errors.name && <span className="text-red-500">{errors.name.message}</span>}

// ✅ 在验证/提交时禁用提交按钮
<button disabled={isSubmitting || !isValid}>提交</button>

响应式布局

/* ✅ 移动优先的断点 */
.container { padding: 1rem; }

@media (min-width: 768px) {
  .container { padding: 2rem; }
}

/* ✅ 适合触摸的按钮尺寸 (最小 44px) */
.btn { min-height: 44px; min-width: 44px; }

/* ✅ 移动端数据表格水平滚动 */
.table-container { overflow-x: auto; }

可访问性 (a11y)

// ✅ 语义化 HTML
<nav>...</nav>
<main>...</main>
<button>点击我</button>  // 不要用 <div onClick>

// ✅ ARIA 标签
<button aria-label="关闭对话框">×</button>

// ✅ 键盘导航
<button onKeyDown={(e) => e.key === 'Enter' && handleClick()}>

// ✅ 焦点指示器
button:focus { outline: 2px solid blue; outline-offset: 2px; }

快速检查清单

  • [ ] 已处理加载/错误状态
  • [ ] 交互元素上使用了 data-testid
  • [ ] 使用路由器 Link,而非 window.location
  • [ ] 辅助函数在使用前已定义
  • [ ] 主要组件已设置错误边界
  • [ ] 触摸目标 ≥ 44px
  • [ ] 图标按钮已添加 ARIA 标签