react-组件规范.md 4.8 KB


description: React 应用的编码标准和最佳实践

React 最佳实践

项目结构

  • 所有前端代码位于 web 目录
  • 主应用代码位于 web/apps/labelstudio
  • 共享库位于 web/libs
  • 遵循既定的目录结构:
    • components/: 可复用的 UI 组件
    • pages/: 顶层页面组件
    • utils/: 工具函数
    • hooks/: 自定义 React Hooks
    • atoms/: Jotai 原子状态定义
    • providers/: Context 提供者
    • services/: API 和其他服务
    • types/: TypeScript 类型定义
    • assets/: 静态资源

组件结构

  • 使用函数组件而非类组件
  • 保持组件小而专注
  • 将可复用逻辑提取到自定义 Hooks
  • 使用组合而非继承
  • 使用 TypeScript 实现适当的 prop 类型
  • 将大组件拆分为更小、更专注的组件
  • 遵循一致的文件组织模式:

    component-name/
    component-name.tsx
    component-name.module.scss
    component-name.test.tsx
    index.ts
    

Hooks 使用

  • 遵循 Hooks 规则(只在顶层调用、只在 React 函数中调用)
  • 使用自定义 Hooks 实现可复用逻辑
  • 保持 Hooks 专注和简单
  • 除非绝对必要,否则避免使用 useEffect
  • 在 useEffect 中使用适当的依赖数组
  • 在 useEffect 中实现清理逻辑
  • 避免嵌套 Hooks

状态管理

  • 使用 useState 管理本地组件状态
  • 使用 Jotai 原子而非 Context API 管理共享状态
  • 使用 atomWithReducer 处理复杂状态逻辑
  • 使用 atomWithQuery 处理任何 API 数据请求
  • 将状态保持在尽可能接近使用位置的地方
  • 通过适当的状态管理避免 prop drilling
  • 仅使用 Jotai 作为全局状态管理的单一数据源

性能优化

  • 实现适当的记忆化(useMemo, useCallback)
  • 对昂贵的组件使用 React.memo
  • 避免不必要的重渲染
  • 实现适当的懒加载
  • 在列表中使用适当的 key props
  • 分析和优化渲染性能
  • 避免在渲染函数中创建新对象或函数

开发工具

  • 使用 Biome 进行代码检查和格式化
  • 遵循 .stylelintrc.json 中定义的 CSS/SCSS 检查规则
  • 使用 TypeScript 确保类型安全
  • 通过监控导入来控制打包大小

表单处理

  • 对表单输入使用受控组件
  • 实现适当的表单验证
  • 正确处理表单提交状态
  • 显示适当的加载和错误状态
  • 对复杂表单使用表单库
  • 为表单实现适当的无障碍功能

错误处理

  • 实现错误边界
  • 正确处理异步错误
  • 显示用户友好的错误消息
  • 实现适当的后备 UI
  • 适当记录错误
  • 优雅处理边缘情况

测试

  • 为组件编写单元测试
  • 为复杂流程实现集成测试
  • 使用 React Testing Library
  • 测试用户交互
  • 测试错误场景
  • 实现适当的模拟数据

无障碍性

  • 确保组件符合 WCAG 2.1 AA 标准
  • 使用语义化 HTML 元素
  • 实现适当的 ARIA 属性
  • 确保键盘导航
  • 使用屏幕阅读器测试
  • 处理焦点管理
  • 为图片提供适当的 alt 文本

代码组织

  • 使用适当的文件命名约定,采用 kebab-case,例如 ListItem -> list-item.tsx
  • 优先每个文件夹一个组件,但必要时将相关组件分组在一起,确保每个文件只有一个组件
  • 组件文件夹应包含一个 SCSS .module.scss 文件,文件名为组件的 kebab-case 形式,例如 ListItem -> list-item.module.scss
  • 实现适当的目录结构
  • UI 组件位于 web/libs/ui
  • 跨应用共享的应用组件(如某些页面级块)位于 web/libs/app-common
  • web/apps 中的代码只能从 web/libs 导入,web/libs 不能从 web/apps 导入
  • web/libs/app-common 中的代码只能从其他 web/libsweb/apps 导入。其他 web/libs 不能从 web/libs/app-common 导入
  • 将原子保存在全局 atoms 文件夹中,文件名与实体或状态意图匹配
  • 通过将 story 文件与组件文件放在一起,将所有组件及其状态添加到 Storybook,例如 list-item.stories.tsx

包导入规范

  • 使用 @humansignal/ui 包获取 UI 组件
  • 使用 @humansignal/icons 包获取图标
  • 使用 @humansignal/core 包获取核心工具/函数
  • 使用 @humansignal/app-common 包获取应用组件

最佳实践

  • 禁止循环导入
  • 使用适当的导入/导出
  • 遵循既定的导入顺序
  • 组合组件而非扩展组件
  • 保持组件专注于单一职责
  • 用清晰的注释记录复杂逻辑
  • 遵循项目的文件夹结构和命名约定
  • 优先使用受控组件而非非受控组件
  • 保持组件的纯净性,避免副作用
  • 使用 PropTypes 或 TypeScript 进行类型检查

组件设计原则

  • 单一职责原则:每个组件只做一件事
  • 可复用性:设计可在多处使用的组件
  • 可组合性:小组件组合成大组件
  • 可测试性:编写易于测试的组件
  • 可维护性:代码清晰易懂,便于维护