关于 react-advanced
react-advanced 是面向 React 应用开发与优化的 React 19 平台功能和渲染架构参考技能,涵盖 React Compiler、并发渲染、Actions、组件模式、性能及 React Server Component 边界。
主要功能
- 01React Compiler 与记忆化指导
- 02并发渲染原语
- 03React 19 Actions 与 API
- 04高级组件架构模式
- 05渲染性能优化方法
- 06React Server Component 边界概念
适用场景
- 01在应用中采用 React Compiler
- 02在高开销渲染期间保持界面响应
- 03使用 React 19 Actions 构建表单
- 04排查上下文引发的重渲染及大列表性能问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill react-advanced安装后在 Claude Code 中输入/react-advanced确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonreferences/component-patterns.mdconcurrent-rendering.mdperformance.mdreact-compiler.mdreact19-actions-and-apis.mdrsc-boundary.md详细介绍
React 进阶:React 19 平台与渲染架构
概述
React 19 时代的平台能力与渲染架构参考。本技能涵盖重塑现代 React 应用构建和优化方式的功能:React Compiler,以及不再需要凭习惯手动记忆化;并发渲染原语;use() Hook;Actions 和表单 Hook;React 19 的易用性改进(ref 作为普通 prop、<Context> 作为 provider、原生元数据);高级组件架构模式;渲染性能工程;以及对 React Server Component 边界的概念性介绍。
本指南将 **React 19(2024 年 12 月)和 React Compiler 1.0(2025 年 10 月稳定版)**视为当前版本。对于新代码,React 19 之前凭习惯使用 useMemo/useCallback/React.memo 包装值的记忆化建议已成为反模式。编译器会自动进行记忆化。权威文档请参阅 react.dev;本技能对其进行提炼和应用,而不是简单复述。
范围说明:本技能不涵盖的内容
本技能专注于 React 19 平台和渲染架构。其他内容请参阅相应的技能:
| 主题 | 所属技能 |
|---|---|
核心 Hook 教程(useState/useEffect/useRef/useMemo/useCallback/useContext)、JSX、props/state、列表、受控输入 | react-core |
| 高级自定义 Hook 组合方案——基于 SWR 的数据 Hook、防抖搜索、记忆化 provider 值模式、判别联合 Hook 状态 | react-hooks-composition |
使用 XState v5 进行显式有限状态机建模(setup()、actors、guards、并行状态) | react-state-machine |
| 通过 React Query 实现服务端状态缓存、查询失效、乐观更新 | tanstack-query |
| 通过不使用 provider 的 store 管理全局客户端状态 | zustand |
Server Components、Server Actions(revalidateTag/revalidatePath)、App Router 数据获取、缓存、Turbopack 的框架集成 | Next.js 技能(nextjs-core、nextjs-v16) |
| 停靠式布局 UI(拖放面板、分隔条) | flexlayout-react |
本技能介绍 React 层面的概念(并发渲染、作为 React 功能的 RSC 边界、作为 React 原语的 Actions)。这些概念在框架中的具体集成方式属于 Next.js 技能的范畴。
何时使用本技能
以下情况可使用本技能:
- 采用 React Compiler,并摆脱旧有的记忆化习惯
- 使用并发功能(
useTransition、useDeferredValue、用于数据的 Suspense)保持 UI 响应流畅 - 使用 React 19 Actions、表单或
use()Hook 构建应用 - 优化渲染性能:context 过度渲染、大型列表、代码拆分
- 设计复合组件、context 选择器、错误边界或 portals
- 从 React 层面理解 RSC /
'use client'边界
React 编译器——手动记忆化的终结
React 编译器于 2025-10-07 达到 1.0 稳定版。它是一种构建时工具,能够以精细粒度自动记忆化组件和钩子,包括手写 useMemo 无法表达的条件式记忆化。它兼容 React 17、18 和 19,并且在 19 上效果最佳。
**与 React 17/18 相比的变化:**长期以来,将值包装在 useMemo/useCallback 中、将组件包装在 React.memo 中的建议,对于新代码已经过时。编译器会处理记忆化。现在凭习惯到处添加手动记忆化只会增加冗余,甚至可能弊大于利。
// BEFORE (pre-compiler reflex): hand-memoize everything
const sorted = useMemo(() => items.slice().sort(compare), [items]);
const onPick = useCallback((id: string) => onSelect(id), [onSelect]);
const Row = React.memo(function Row({ item }: { item: Item }) { /* ... */ });
// AFTER (compiler enabled): write plain code; the compiler memoizes
const sorted = items.slice().sort(compare);
const onPick = (id: string) => onSelect(id);
function Row({ item }: { item: Item }) { /* ... */ }
手动记忆化仍然重要的情况(备用方案):
- 计算值会传入副作用依赖数组,为了保证正确性(而不只是性能),必须保持引用稳定。
- 编译器无法静态分析的代码——编译器会安全地跳过这类组件,而不是错误地编译它们,因此手动记忆化仍是有效的局部优化。
**现有代码:**编译器会有意保留手动记忆化;preserve-manual-memoization lint 规则会标记那些对运行至关重要的记忆化。启用编译器后,不要盲目删除 useMemo/useCallback。
**采用路径:**安装 eslint-plugin-react-hooks v6+(它整合了之前的 eslint-plugin-react-compiler)→ 修复报告的 React 规则违规 → 在构建中启用编译器(Babel / Vite / Metro / Rsbuild)。React DevTools 会在经过编译器优化的组件上显示 “Memo ✨” 徽标。
完整的采用指南、各打包器的配置方法及优化前后分析,请参阅:react-compiler.md。
并发渲染
并发特性允许 React 中断并调整渲染优先级,使紧急更新(输入文字)保持响应,同时让耗时更新(筛选大型列表)延后处理。
useTransition将状态更新标记为非紧急,并提供isPending。React 会在后台渲染过渡期间,保持旧界面可交互。- React 19 异步过渡:
startTransition接受异步函数。需要注意的是:在await之后发起的状态更新会脱离过渡,除非再次用startTransition包装。 useDeferredValue会生成一个滞后的值副本,并且支持中断,能适应设备性能。对于耗时的派生渲染,优先使用它,而不是固定时长的setTimeout防抖;React 19 还增加了initialValue。- **数据的 Suspense:**遇到抛出的 promise(或通过
use()读取的 promise)时会暂停,并显示最近的<Suspense fallback>。更改key会重置边界。
function ProductSearch({ allProducts }: { allProducts: Product[] }) {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query); // lags behind input under load
// Filtering reads the deferred value, so typing stays responsive.
const results = allProducts.filter((p) => p.name.includes(deferredQuery));
return (
<>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
<ResultsList results={results} stale={query !== deferredQuery} />
</>
);
}
React 层级的流式 SSR(renderToPipeableStream、外壳设计、19.2 中 Suspense 内容显示的批处理)详见 concurrent-rendering.md;框架的流式处理细节请参阅 Next.js 技能。
React 19 平台钩子与 API
use() 钩子
use() 用于读取 promise 或 context 值,并且可以有条件地调用——包括提前返回之后。这是 Hooks 规则中特意设定的例外。它不能放在 try/catch 内;应通过错误边界处理被拒绝的 promise。最好在组件树较高层(或服务器上)创建 promise 后再向下传递,因为在渲染期间创建的 promise 会在每次渲染时重新创建。
Actions
Actions 是 React 层级的异步变更基本机制,独立于任何框架:
useActionState(从 canary 版useFormState更名而来)运行一个 action,跟踪待处理状态和错误状态,并将上一次结果传递下去。useOptimistic会在 action 执行期间渲染乐观值,并在完成后自动还原。useFormStatus可从子组件读取外层<form>的待处理状态,无需逐层传递属性。<form action={fn}>会将函数直接关联到表单提交,并在成功后自动重置。
function NameForm({ save }: { save: (name: string) => Promise<string> }) {
const [error, submit, isPending] = useActionState(
async (_prev: string | null, formData: FormData) => {
const result = await save(formData.get('name') as string);
return result.startsWith('error') ? result : null;
},
null,
);
return (
<form action={submit}>
<input name="name" disabled={isPending} />
{error && <p role="alert">{error}</p>}
</form>
);
}
更符合人体工学的变化
ref是普通 prop。forwardRef已弃用(codemod 会迁移现有用法);函数组件会像接收其他 prop 一样接收ref。<Context value>取代了现已成为旧版 API 的<Context.Provider>。- 原生文档元数据:
<title>、<meta>和<link>会自动提升到<head>,取代react-helmet。preload/preinit/preconnect用于处理资源提示。
完整示例及从 17/18 迁移的说明:react19-actions-and-apis.md。
高级组件模式
- 复合组件通过 context 共享隐式状态,让父组件和子组件无需逐层传递 prop 即可协同工作(
<Tabs>/<Tabs.Tab>)。 - Context 优化: 原生 context 没有选择器。provider 值发生任何变化时,所有消费者都会重新渲染;
React.memo无法阻止由 context 触发的重新渲染,而use(Context)支持有条件读取,但不支持选择性订阅。编译器无法解决大型 context 导致的过度渲染问题。原生解决方案是对 provider 值进行记忆化,并按变化频率拆分 context;用户空间的use-context-selector则支持对切片进行订阅(但存在 tearing/旧版 API 相关注意事项)。 - Render props 与自定义 hooks: 复用逻辑时 hooks 更合适;对于无头的“渲染什么”组件,render props 仍然有用。
- 错误边界仍基于 class;
react-error-boundary提供了一个 hook(useErrorBoundary),用于处理原生错误边界无法捕获的异步错误和事件处理程序错误。React 19 会将已捕获的错误只记录一次,并新增onCaughtError/onUncaughtError。 - Portal(
createPortal)只会改变 DOM 中的位置——context 和错误仍沿 React 树传播,而非沿 DOM 树传播。
决策指南和完整示例:component-patterns.md。
性能架构
- 虚拟化只渲染可见行。
@tanstack/react-virtual是现代无头方案,TypeScript 支持最出色;react-window已成熟但停滞不前;react-virtuoso则开箱即用。完成虚拟化后,单项渲染器的成本会成为瓶颈——应让行组件保持轻量。 - 代码拆分使用
React.lazy+Suspense,优先按路由拆分。避免把很小的组件过度拆分成许多小于 10KB 的块,这只会增加请求开销,并无收益。 - 性能分析使用 React DevTools Profiler 对生产构建进行分析,查看实际重新渲染了什么以及原因;Why-Did-You-Render 可帮助追踪可避免的渲染。
库对比、代码拆分策略,以及完整的反模式 → 检测 → 修复表:performance.md。
RSC / 'use client' 边界(概念)
React Server Components 会预先渲染,不能持有状态或运行副作用,并会生成可序列化的输出。边界由模块依赖图定义(在模块顶部添加 'use client' 指令),而非由渲染树定义。传入 Client Component 的 prop 必须可序列化;Client Component 仍可将作为 children 传入的 Server Component 渲染出来。'use server' 指令用于标记 Server Functions,其参数不可信,必须经过验证和授权。
明确延后: 缓存、路由加载器和 App Router 数据获取属于 Next.js 技能范围。请固定 React 版本,因为 RSC 打包器 API 在 19.x 中不遵循 semver 稳定性。概念模型和框架交接说明:rsc-boundary.md。
应避免的反模式
❌ 不要:启用编译器后仍对所有内容手动记忆化
// BAD: redundant manual memo once the compiler is on; adds noise and cost
const value = useMemo(() => ({ a, b }), [a, b]);
const onClick = useCallback(() => doThing(a), [a]);
// GOOD: write plain code; let the compiler memoize
const value = { a, b };
const onClick = () => doThing(a);
❌ 不要:启用编译器后盲目移除手动记忆化
// BAD: removing memo that stabilized an effect dependency changes behavior
const config = { endpoint, token }; // recreated each render → effect re-fires
useEffect(() => subscribe(config), [config]);
// GOOD: keep the deliberate escape hatch the preserve-manual-memoization lint protects
const config = useMemo(() => ({ endpoint, token }), [endpoint, token]);
useEffect(() => subscribe(config), [config]);
❌ 不要:将高频变化状态放入一个大型 context
// BAD: every consumer re-renders when any field changes; memo cannot block it
const AppContext = createContext<{ theme: Theme; cursor: Point } | null>(null);
// GOOD: split by change frequency so fast-changing state is isolated
const ThemeContext = createContext<Theme | null>(null); // changes rarely
const CursorContext = createContext<Point | null>(null); // changes often
❌ 不要:在异步 transition 中的 await 之后更新状态
// BAD: the post-await update escapes the transition; isPending ends early
startTransition(async () => {
const data = await load();
setData(data); // not part of the transition
});
// GOOD: re-wrap the post-await update
startTransition(async () => {
const data = await load();
startTransition(() => setData(data));
});
❌ 不要:在新的 React 19 代码中保留 forwardRef / <Context.Provider> / react-helmet
// BAD: superseded idioms in new code
const Input = forwardRef<HTMLInputElement, Props>((props, ref) => <input ref={ref} {...props} />);
<ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>;
// GOOD: ref as a plain prop, <Context> as provider, native metadata
function Input({ ref, ...props }: Props & { ref?: React.Ref<HTMLInputElement> }) {
return <input ref={ref} {...props} />;
}
<ThemeContext value={theme}>{children}</ThemeContext>;
只有当 Props 是必须公开 ref 的自定义接口时,才需要 & { ref?: ... } 这个交叉类型。对于包装内置元素的组件,从 React.ComponentProps<'input'> 派生 Props 时已包含类型正确的 ref,因此交叉类型是多余的。
何时使用相关技能
- react-core:基础知识——组件、JSX、props/state、核心 Hooks、列表、受控输入。
- react-hooks-composition:自定义 Hook 组合方案——SWR 数据 Hook、防抖搜索、记忆化 Provider、异步状态 Hook。
- react-state-machine:针对复杂流程使用 XState v5 显式定义有限状态机,使不可能的状态无法表示。
- tanstack-query / zustand:分别用于服务器状态缓存和全局客户端状态。
- Next.js skills:框架层面的 Server Components、Server Actions、路由和缓存配置。
最佳实践摘要
- 优先启用编译器:启用
eslint-plugin-react-hooksv6+,修复 Rules of React 问题,然后启用 React Compiler。 - 停止条件反射式记忆化:仅在有意规避限制时才使用
useMemo/useCallback/React.memo(例如保持 Effect 依赖稳定,或处理无法分析的代码)。 - 借助并发机制保持响应能力:对于开销大的渲染,优先使用
useTransition/useDeferredValue,而不是手动防抖;对await之后的更新重新包装。 - 使用 Actions 执行变更:
useActionState+useOptimistic+useFormStatus可在 React 层处理待处理、错误和乐观状态。 - 正确使用
use():可以有条件地调用,绝不能放在try/catch中,并在组件树较高层创建 Promise。 - 采用 React 19 的便捷用法:将
ref作为 prop、使用<Context value>、采用原生元数据——移除forwardRef和react-helmet。 - 从结构上解决 context 过度渲染:记忆化 value 并拆分 context;编译器无法解决此问题。
- 优化列表和包性能:对大型列表进行虚拟化,按路由拆分代码,并针对生产构建进行性能分析。
- 遵守 RSC 边界:边界基于模块图;确保跨边界传递的 props 可序列化,验证服务器函数的输入,并固定 React 版本。
导航
- React Compiler:按打包工具采用编译器、ESLint/Rules of React、编译器会跳过的内容、
preserve-manual-memoization、前后对比示例。 - Concurrent Rendering:
useTransition(同步/异步 + await 后的注意事项)、useDeferredValue、用于数据的 Suspense、流式 SSR 外壳、批量显示、边界key重置。 - React 19 Actions & APIs:
use()、useActionState、useOptimistic、useFormStatus、<form action>、ref-as-prop、useImperativeHandle、<Context value>、元数据/预加载,以及迁移说明。 - Component Patterns:复合组件、context 选择器/拆分 +
use-context-selector、render props 与 Hooks 的比较、错误边界、portal。 - Performance:虚拟化库对比、代码拆分策略、Profiler 工作流、反模式 → 检测 → 修复目录。
- RSC Boundary:
'use client'/'use server'概念模型、序列化规则、服务器函数安全、与 Next.js 的衔接、版本固定。
参考资料
- React Documentation — 本技能中所有 API 的权威来源
- React Compiler 1.0
- React 19 release
- React 19.2
- Rules of Hooks