关于 react
面向 React 18/19 的开发技能,提供编写和修改组件时的约定,涵盖状态、Effect、无障碍与测试,并避免无要求地重构未改动文件。
主要功能
- 01默认使用 Server Component
- 02状态与 Effect 指引
- 03错误边界与 Suspense 边界
- 04React 19 API 约定
- 05无障碍标记与测试
适用场景
- 01审查 React 组件改动
- 02避免回调中的状态过期
- 03安排加载占位内容
- 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