mcpField
R
react

react

github.com/alexander-danilenko开发1883 次安装2 周前更新
代码仓库

关于 react

面向 React 18/19 的开发技能,提供编写和修改组件时的约定,涵盖状态、Effect、无障碍与测试,并避免无要求地重构未改动文件。

主要功能

  1. 01默认使用 Server Component
  2. 02状态与 Effect 指引
  3. 03错误边界与 Suspense 边界
  4. 04React 19 API 约定
  5. 05无障碍标记与测试

适用场景

  1. 01审查 React 组件改动
  2. 02避免回调中的状态过期
  3. 03安排加载占位内容
  4. 04按无障碍角色测试控件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/alexander-danilenko/cortex-ai-skills --skill react

安装后在 Claude Code 中输入/react确认已加载。

详细介绍

React

React 18/19 的团队约定。编写或修改组件时请遵循这些约定——除非有人要求,否则不要重构未触及的文件来匹配这些约定。

约定

  • 默认使用服务端组件;仅在需要时添加 'use client'——状态、效果、事件处理器、浏览器 API。尽可能将边界往树的下层移动:'use client' 标记上方的每个组件也都会发送到浏览器。任何跨越该边界的内容都必须可序列化——属性对象中的函数、类实例或 Date 会在运行时而不是构建时出错。
  • 在任何生命周期超过当前渲染的代码中,通过函数式更新器读取状态——例如定时器、订阅、经过防抖的回调。在 useEffect(…, []) 中调用 setCount(count + 1) 会永远捕获首次渲染时的 count,并在每次触发时悄悄将其设为 1;setCount(c => c + 1) 则始终读取当前状态。
  • Effect 用于与 React 之外的事物同步——例如订阅、定时器、非 React 小部件。数据转换应在渲染时进行,派生值应存入普通变量,事件响应则应放在处理器中。大多数 useEffect 错误都源于使用了本不该存在的 Effect。
  • 每个启动某项操作的 Effect 都必须返回清理函数,用于停止该操作。严格模式会在开发环境中将 Effect 调用两次,正是为了让缺少清理函数的问题显现出来——把它当作应有的信号,而不是噪声。
  • Key 必须表示稳定的身份,而不是位置。 使用数组索引作为 key,会使 React 在列表重新排序时复用错误的 DOM 节点,最终表现为状态关联到了错误的行。
  • 基于可衡量的理由进行记忆化。 memo、useMemo 和 useCallback 都会增加一次比较操作和需要阅读的代码。只有在子组件确实开销很大,或子组件本身已记忆化且新的引用会导致记忆化失效时,它们才值得使用——不要默认套用。
  • 状态应放在最合适的层级。 useState 用于本地状态,仅在有共享祖先时才向上提升。确实存在全局客户端状态时使用 Zustand;服务端状态使用 TanStack Query,因为缓存失效和重新获取正是它的职责,而在 Effect 中手动实现这些逻辑很容易悄无声息地出错。
  • 对任何可能独立出错的部分使用错误边界——例如路由、小部件、第三方嵌入内容。没有错误边界时,渲染错误会卸载整棵组件树,用户看到的将是一片空白。
  • 在需要显示备用 UI 的位置设置 Suspense 边界,并将边界放在加载 UI 与其将替换的布局相匹配的位置。将边界放在根节点会让任何待处理的请求都触发全页加载动画。
  • React 19:使用 useActionState 和 <form action> 处理变更,使用 useOptimistic 提供即时反馈,使用 use() 有条件地读取 Promise 或上下文。ref 是普通属性——不再需要 forwardRef。useFormStatus 只能报告其上方表单的状态,因此,读取待提交状态的提交按钮必须是嵌套在 <form> 内的独立组件——在渲染表单的组件中调用它始终会返回 pending: false。
  • 在击键会触发开销较大的工作时使用 useTransition。 紧急更新输入内容,并将派生工作标记为过渡更新,这样 React 就能中断它;否则,即便没有任何报错,在会筛选大型列表的字段中输入也会让人觉得出了问题。
  • 优先使用语义化 HTML,仅在需要补充时使用 ARIA。 <button> 自带焦点处理、键盘激活和角色;<div role="button"> 则意味着必须正确重新实现这三项功能。
  • 按角色和标签查询测试元素,而不是使用测试 ID。 getByRole('button', { name: /submit/i }) 会在控件无法再以用户操作的方式访问时失败——这正是测试应该捕获的问题。getByTestId 无论如何都会通过;对于没有可访问名称的元素,它才是备用方案。

评论

支持 Markdown