react-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReact Patterns
React模式
Performance and composition patterns for React 19 + Vite + Cloudflare Workers projects. Use as a checklist when writing new components, a review guide when auditing existing code, or a refactoring playbook when something feels slow or tangled.
Rules are ranked by impact. Fix CRITICAL issues before touching MEDIUM ones.
适用于React 19 + Vite + Cloudflare Workers项目的性能与组合模式。可作为编写新组件时的检查清单、审计现有代码时的评审指南,或是在页面卡顿或代码混乱时的重构手册。
规则按影响优先级排序。先修复CRITICAL(严重)问题,再处理MEDIUM(中等)问题。
When to Apply
适用场景
- Writing new React components or pages
- Reviewing code for performance issues
- Refactoring components with too many props or re-renders
- Debugging "why is this slow?" or "why does this re-render?"
- Building reusable component libraries
- Code review before merging
- 编写新的React组件或页面
- 评审代码中的性能问题
- 重构拥有过多属性或重复渲染的组件
- 调试“为什么这么卡?”或“为什么会重复渲染?”的问题
- 构建可复用组件库
- 代码合并前的评审
1. Eliminating Waterfalls (CRITICAL)
1. 消除请求瀑布(CRITICAL)
Sequential async calls where they could be parallel. The #1 performance killer.
| Pattern | Problem | Fix |
|---|---|---|
| Await in sequence | | |
| Fetch in child | Parent renders, then child fetches, then grandchild fetches | Hoist fetches to the highest common ancestor, pass data down |
| Suspense cascade | Multiple Suspense boundaries that resolve sequentially | One Suspense boundary wrapping all async siblings |
| Await before branch | | Move await inside the branch — don't fetch what you might not use |
| Import then render | | Use |
How to find them: Search for in components. Each is a potential waterfall. If two awaits are independent, they should be parallel.
awaitawait本应并行的异步调用却按顺序执行,这是头号性能杀手。
| 模式 | 问题 | 修复方案 |
|---|---|---|
| 顺序await | | |
| 子组件中发起请求 | 父组件渲染,然后子组件发起请求,接着孙组件发起请求 | 将请求提升到最近的共同祖先组件,再向下传递数据 |
| Suspense级联 | 多个Suspense边界按顺序解析 | 用一个Suspense边界包裹所有异步兄弟组件 |
| 分支判断前await | | 将await移到分支内部——不要请求可能用不到的数据 |
| 先导入再渲染 | | 使用 |
排查方法:在组件中搜索关键字。每个都可能是请求瀑布的源头。如果两个await是独立的,就应该并行执行。
awaitawait2. Bundle Size (CRITICAL)
2. 打包体积优化(CRITICAL)
Every KB the user downloads is a KB they wait for.
| Pattern | Problem | Fix |
|---|---|---|
| Barrel imports | | |
| No code splitting | Heavy component loaded on every page | |
| Third-party at load | Analytics/tracking loaded before the app renders | Load after hydration: |
| Full library import | | |
| Lucide tree-shaking | | Explicit map: |
| Duplicate React | Library bundles its own React → "Cannot read properties of null" | |
How to find them: — shows what's in your bundle.
npx vite-bundle-visualizer用户下载的每1KB内容都意味着等待时间的增加。
| 模式 | 问题 | 修复方案 |
|---|---|---|
| 桶导入 | | 直接导入: |
| 未做代码分割 | 大型组件在所有页面都被加载 | 使用 |
| 第三方库初始加载 | 分析/追踪库在应用渲染前就被加载 | hydration后加载: |
| 导入完整库 | | 按需导入: |
| Lucide图标未摇树 | | 显式导入: |
| 重复React实例 | 库自带了React → 出现"Cannot read properties of null"错误 | 在vite.config.ts中配置 |
排查方法:执行——查看打包内容的构成。
npx vite-bundle-visualizer3. Composition Architecture (HIGH)
3. 组合架构(HIGH)
How you structure components matters more than how you optimise them.
| Pattern | Problem | Fix |
|---|---|---|
| Boolean prop explosion | | Explicit variants: |
| Compound components | Complex component with 15 props | Split into |
| renderX props | | Use children + named slots: |
| Lift state | Sibling components can't share state | Move state to parent or context provider |
| Provider implementation | Consumer code knows about state management internals | Provider exposes interface |
| Inline components | | Define Child outside Parent — inline components remount on every render |
The test: If a component has more than 5 boolean props, it needs composition, not more props.
组件的结构设计比优化技巧更重要。
| 模式 | 问题 | 修复方案 |
|---|---|---|
| 布尔属性爆炸 | | 显式变体: |
| 复合组件 | 拥有15个属性的复杂组件 | 拆分为 |
| renderX属性 | | 使用子组件+命名插槽: |
| 状态提升 | 兄弟组件无法共享状态 | 将状态移到父组件或上下文提供者中 |
| 提供者实现 | 消费者代码知晓状态管理的内部细节 | 提供者暴露接口 |
| 内联组件 | | 将Child定义在Parent外部——内联组件会在每次渲染时重新挂载 |
测试标准:如果一个组件的布尔属性超过5个,就需要通过组合重构,而不是增加更多属性。
4. Re-render Prevention (MEDIUM)
4. 防止重复渲染(MEDIUM)
Not all re-renders are bad. Only fix re-renders that cause visible jank or wasted computation.
| Pattern | Problem | Fix |
|---|---|---|
| Default object/array props | | Hoist: |
| Derived state in effect | | Derive during render: |
| Object dependency | | Use primitive deps: |
| Subscribe to unused state | Component reads | Split context or use selector: |
| State for transient values | | Use |
| Inline callback props | | |
How to find them: React DevTools Profiler → "Why did this render?" or double-renders in dev.
<React.StrictMode>并非所有重复渲染都是问题。仅修复那些导致可见卡顿或计算浪费的重复渲染。
| 模式 | 问题 | 修复方案 |
|---|---|---|
| 默认对象/数组属性 | | 提升默认值: |
| Effect中派生状态 | | 渲染时派生: |
| 对象依赖项 | | 使用原始类型依赖: |
| 订阅未使用的状态 | 组件读取 | 拆分上下文或使用选择器: |
| 瞬态值用状态存储 | | 使用 |
| 内联回调属性 | | 使用 |
排查方法:React DevTools Profiler → "Why did this render?" 或在开发环境中使用的双重渲染检测。
<React.StrictMode>5. React 19 Specifics (MEDIUM)
5. React 19专属特性(MEDIUM)
Patterns that changed or are new in React 19.
| Pattern | Old (React 18) | New (React 19) |
|---|---|---|
| Form state | | |
| Ref forwarding | | |
| Context | | |
| Pending UI | Manual loading state | |
| Route-level lazy | Works with | Still true — |
| Optimistic updates | Manual state management | |
| Metadata | Helmet or manual | |
React 19中变更或新增的模式。
| 模式 | 旧版(React 18) | 新版(React 19) |
|---|---|---|
| 表单状态 | | |
| Ref转发 | | |
| 上下文 | | |
| 等待状态UI | 手动管理加载状态 | |
| 路由级懒加载 | 仅支持 | 依然如此——使用 |
| 乐观更新 | 手动管理状态 | |
| 元数据 | Helmet或手动管理 | 在组件JSX中直接使用 |
6. Rendering Performance (MEDIUM)
6. 渲染性能优化(MEDIUM)
| Pattern | Problem | Fix |
|---|---|---|
| Layout shift on load | Content jumps when async data arrives | Skeleton screens matching final layout dimensions |
| Animate SVG directly | Janky SVG animation | Wrap in |
| Large list rendering | 1000+ items in a table/list | |
| content-visibility | Long scrollable content renders everything upfront | |
| Conditional render with && | | Use ternary: |
| 模式 | 问题 | 修复方案 |
|---|---|---|
| 加载时布局偏移 | 异步数据到达时内容跳动 | 使用与最终布局尺寸匹配的骨架屏 |
| 直接动画SVG | SVG动画卡顿 | 包裹在 |
| 大型列表渲染 | 表格/列表中有1000+条数据 | 使用 |
| content-visibility | 长滚动内容初始时渲染所有元素 | 为屏幕外的部分添加 |
| 用&&做条件渲染 | | 使用三元表达式: |
7. Data Fetching (MEDIUM)
7. 数据请求优化(MEDIUM)
| Pattern | Problem | Fix |
|---|---|---|
| No deduplication | Same data fetched by 3 components | TanStack Query or SWR — automatic dedup + caching |
| Fetch on mount | | TanStack Query: |
| No optimistic update | User clicks save, waits 2 seconds, then sees change | |
| Stale closure in interval | | |
| Polling without cleanup | | Return cleanup: |
| 模式 | 问题 | 修复方案 |
|---|---|---|
| 无请求去重 | 3个组件请求相同数据 | 使用TanStack Query或SWR——自动去重+缓存 |
| 挂载时请求 | | TanStack Query: |
| 无乐观更新 | 用户点击保存后,等待2秒才看到变化 | 使用 |
| 定时器中的闭包过期 | | 使用 |
| 无清理的轮询 | useEffect中的 | 返回清理函数: |
8. Vite + Cloudflare Specifics (MEDIUM)
8. Vite + Cloudflare专属配置(MEDIUM)
| Pattern | Problem | Fix |
|---|---|---|
| Undefined — only works in Vite-processed files | Use |
| React duplicate instance | Library bundles its own React | |
| Radix Select empty string | | Use sentinel: |
| React Hook Form null | | Spread manually: |
| Env vars at edge | | Use |
| 模式 | 问题 | 修复方案 |
|---|---|---|
Node脚本中使用 | 未定义——仅在Vite处理的文件中可用 | 使用Vite的 |
| 重复React实例 | 库自带了React | 在vite.config.ts中配置 |
| Radix Select空字符串值 | | 使用标记值: |
| React Hook Form空值问题 | | 手动展开: |
| 边缘环境中的环境变量 | Workers中不存在 | 使用 |
Using as a Review Checklist
作为代码评审检查清单使用
When reviewing code, go through categories 1-3 (CRITICAL + HIGH) for every PR. Categories 4-8 only when performance is a concern.
/react-patterns [file or component path]Read the file, check against rules in priority order, report findings as:
file:line — [rule] description of issue评审代码时,对每个PR都要检查第1-3类(CRITICAL + HIGH)的规则。仅当存在性能问题时才需要检查第4-8类。
/react-patterns [文件或组件路径]阅读文件,按优先级对照规则检查,按以下格式报告问题:
file:line — [规则] 问题描述
```",