mcpField
R
react19-patterns

react19-patterns

github.com/qingqishi开发558 次安装今天更新
代码仓库

关于 react19-patterns

面向启用 React Compiler 的 React 19 项目的编码技能,介绍 Context 与 `use()` 写法、由编译器处理优化,以及 ViewTransition 与 Suspense 的边界配置。

主要功能

  1. 01React 19 Context provider 语法
  2. 02使用 `use()` 替代 `useContext()`
  3. 03依靠编译器执行记忆化
  4. 04避免不必要的手动优化
  5. 05协调 ViewTransition 与 Suspense

适用场景

  1. 01在 React 19 组件中使用 Context
  2. 02移除多余的手动记忆化
  3. 03通过 Suspense 避免水合不匹配
  4. 04先分析性能再添加手动优化

安装

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

$npx skills add https://github.com/qingqishi/shiqingqi.com --skill react19-patterns

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

详细介绍

React 19 模式

概述

本项目使用启用了 React Compiler 的 React 19。这会改变 React 代码的编写方式,尤其是 Context 和优化方面。

React 19 Context 模式

使用简写语法

React 19 为 Context provider 引入了简写语法。

✅ 正确(React 19):

<MyContext value={someValue}>
  <ChildComponents />
</MyContext>

❌ 错误(旧模式):

<MyContext.Provider value={someValue}>
  <ChildComponents />
</MyContext.Provider>
使用 use() Hook,而不是 useContext()

React 19 引入了用于使用 context 的 use() Hook。

✅ 正确(React 19):

import { use } from "react";
import { MyContext } from "./MyContext";

function MyComponent() {
  const value = use(MyContext);
  return <div>{value}</div>;
}

❌ 错误(旧模式):

import { useContext } from "react";
import { MyContext } from "./MyContext";

function MyComponent() {
  const value = useContext(MyContext);
  return <div>{value}</div>;
}

已启用 React Compiler

无需手动记忆化

React Compiler 会自动优化组件并处理记忆化。不要使用手动记忆化模式。

✅ 正确(由 React Compiler 处理):

function MyComponent({ items }) {
  // React Compiler automatically memoizes this computation
  const filteredItems = items.filter((item) => item.active);

  // React Compiler automatically stabilizes this function reference
  const handleClick = (id) => {
    console.log(id);
  };

  return (
    <div>
      {filteredItems.map((item) => (
        <button key={item.id} onClick={() => handleClick(item.id)}>
          {item.name}
        </button>
      ))}
    </div>
  );
}

❌ 错误(无需手动记忆化):

import { useMemo, useCallback, memo } from "react";

function MyComponent({ items }) {
  // ❌ Don't use useMemo - React Compiler handles this
  const filteredItems = useMemo(
    () => items.filter((item) => item.active),
    [items],
  );

  // ❌ Don't use useCallback - React Compiler handles this
  const handleClick = useCallback((id) => {
    console.log(id);
  }, []);

  return <div>...</div>;
}

// ❌ Don't use memo() - React Compiler handles this
export default memo(MyComponent);

React 19 ViewTransition + Suspense 模式

水合问题

使用 <ViewTransition> 包装包含 Suspense 边界的内容时,如果部分子项位于 Suspense 中,而其他子项不在其中,可能会遇到水合错误。

错误消息:

A tree hydrated but some attributes of the server rendered HTML didn't match the client properties.
This won't be patched up. This can happen if a SSR-ed Client Component used...
Specifically: style={{view-transition-name:"_T_0_"}}

根本原因:

  • ViewTransition 使用“即时”机制,仅在触发转换时应用 view-transition-name 样式
  • SSR 水合期间,非 Suspense 子项中的内容显示会触发 ViewTransition 激活
  • 这会导致客户端在水合期间应用服务器 HTML 中不存在的样式
  • React 检测到不匹配,并记录水合警告
解决方案:保持 Suspense 边界一致

✅ 正确(所有内容都放在 Suspense 中):

<ViewTransition>
  <Suspense fallback={<HeaderSkeleton />}>
    <Header />
  </Suspense>
  <Suspense fallback={null}>{children}</Suspense>
</ViewTransition>

❌ 错误(混合使用 Suspense 和非 Suspense):

<ViewTransition>
  <Suspense fallback={<HeaderSkeleton />}>
    <Header />
  </Suspense>
  {children} {/* NOT in Suspense - causes hydration error! */}
</ViewTransition>

替代方案(将 Suspense 放在 ViewTransition 外部):

<Suspense fallback={<LoadingSkeleton />}>
  <ViewTransition>
    <Header />
    {children}
  </ViewTransition>
</Suspense>

注意:如果 Header 和子项需要独立加载,此替代方案会强制所有内容进入相同的加载状态,可能并不理想。

此修复的原理

将所有子项都包装在 Suspense 边界中:

  • 内容显示会通过 React 的 Suspense 机制进行协调
  • ViewTransition 不会在水合期间过早激活
  • 服务器端和客户端渲染保持一致
  • 不会发生水合不匹配

关键规则

  1. Context 简写:始终使用 <Context value={...}>,而不是 <Context.Provider value={...}>
  2. use() Hook:始终使用 use(Context),而不是 useContext(Context)
  3. 不使用 useMemo:React Compiler 会自动记忆化开销较大的计算
  4. 不使用 useCallback:React Compiler 会自动稳定函数引用
  5. 不使用 memo():React Compiler 会自动优化组件重新渲染
  6. 信任编译器:让 React Compiler 处理优化,而不是使用手动模式
  7. ViewTransition + Suspense:将 ViewTransition 与 Suspense 搭配使用时,确保所有子项都位于 Suspense 边界内,以避免水合错误

可能需要手动优化的情况

在少数情况下,你可能仍需要手动优化:

  • 集成需要稳定引用的外部库
  • 性能分析显示存在 React Compiler 无法发现的特定问题

添加手动优化之前,务必先进行性能分析。React Compiler 非常有效。

评论

支持 Markdown