React
仅使用函数组件
始终使用带命名导出的 TSX 函数组件。属性
创建一个名为{ComponentName}Props 的类型。 使用解构。 不要使用 React.FC。
禁止仅为单个 prop 使用展开
状态管理
使用 Jotai 原子管理全局状态
- 优先使用原子,而非 props 逐层传递
- 不要将
useRef用于状态 — 使用useState或原子。 - 对列表使用原子族和选择器。
避免不必要的重新渲染
- 将
useEffect和数据获取提取到同级的 sidecar 组件中。 - 优先使用事件处理器(
handleClick、handleChange)而不是useEffect。 - 不要使用
React.memo()— 请改为修复根本原因。 - 限制
useCallback/useMemo的使用。
TypeScript
- 优先用
type而非interface— 更灵活、更易组合。 - 优先用字符串字面量而非枚举 — 但 GraphQL 代码生成的枚举和内部库 API 除外。
- 禁止
any— 强制启用严格的 TypeScript。 - 不使用类型导入 — 使用常规导入(由 Oxlint
typescript/consistent-type-imports强制执行)。 - 使用 Zod 对无类型对象进行运行时校验。
JavaScript
命名
- 变量:使用 camelCase,具描述性(
email而非value,fieldMetadata而非fm)。 - 常量:SCREAMING_SNAKE_CASE
- 类型/类:PascalCase
- 文件/目录:kebab-case(
.component.tsx、.service.ts、.entity.ts) - 事件处理器:
handleClick(处理函数不要使用onClick作为名称) - 组件 props:以组件名作为前缀(
ButtonProps)。 - 样式化组件:以
Styled作为前缀(StyledTitle)。
样式
使用 Linaria 的样式化组件。 使用主题值 — 避免硬编码px、rem 或颜色。
导入
使用别名而不是相对路径:文件夹架构
- 模块可以相互导入,但
ui/应保持无依赖 - 将模块私有代码放在
internal/子文件夹中 - 组件不超过 300 行,服务不超过 500 行。