React 19 正式发布:带你看懂所有新特性与升级建议

273 阅读3分钟

React 19 在 2024 年 12 月横空出世,距离上次大版本整整两年。本文帮你提炼“最有用”的更新,读完即可决定要不要升级、怎么升级。

一、Actions:异步交互的“官方范式”

过去,异步逻辑(提交表单、调用接口)的 loading、error、乐观更新全部要自己写。React 19 把这一整套收归官方,起名 Actions


    
    
    
  import { useActionState } from 'react';

function UpdateName() {
  const [error, submitAction, isPending] = useActionState(
    async (prev, formData) => {
      const err = await updateName(formData.get('name'));
      if (err) return err;          // 返回错误即显示
      redirect('/profile');         // 成功就跳转
    },
    null                            // 初始错误值
  );

  return (
    <form action={submitAction}>
      <input name="name" />
      <button disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </form>
  );
}

关键点

  • • 把异步函数直接塞给 action 属性,React 自动追踪 isPending
  • • 错误可返回任意值,组件内直接渲染。
  • • 与 <form> 原生行为深度整合,CSR/SSR 同构体验一致。

二、三大新 Hook 速览

| Hook | 作用 | 旧替代品 |
| | | |
| useActionState | 拿到 action 的 error / pending / submit 函数 | useFormState(已废弃) |
| useFormStatus | 在任意子组件里读取父表单提交状态,告别“prop 钻井” | 无 |
| useOptimistic | 乐观更新:先改 UI,再等服务端响应 | 手动 setState |

useOptimistic 示例:


    
    
    
  function Thread({ messages }) {
  const [optimisticMsgs, addOptimistic] = useOptimistic(
    messages,
    (state, newMsg) => [...state, { text: newMsg, pendingtrue }]
  );

  async function sendMessage(formData) {
    const msg = formData.get('message');
    addOptimistic(msg);   // 立即渲染
    await deliverMessage(msg);
  }

  return (
    <>
      {optimisticMsgs.map((m, i) => (
        <div key={i} style={{ opacity: m.pending ? 0.5 : 1 }}>
          {m.text}
        </div>
      ))}
      <form action={sendMessage}>
        <input name="message" />
      </form>
    </>
  );
}

三、“use” 新钩子:可条件调用的“超级钩子”

use 既能读取 Promise,也能读 Context,而且可以写在条件分支里,突破“Hooks 不能写在 if” 的铁律。


    
    
    
  function Message({ messagePromise }) {
  const message = use(messagePromise); // 暂停直到 resolve
  return <p>{message}</p>;
}

四、ref 直接当 prop,forwardRef 正式退休


    
    
    
  function Input({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

无需再包一层 forwardRef,代码更扁平。

五、文档元数据“组件化”

在任意组件里写 <title><meta><link>,React 会自动 hoist 到 <head>,服务端渲染同样适用。


    
    
    
  function BlogPost({ post }) {
  return (
    <article>
      <title>{post.title}</title>
      <meta name="description" content={post.excerpt} />
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

六、样式与脚本加载更智能

  • <link rel="stylesheet"><script> 放在 Suspense 边界内不会阻塞渲染
  • • 新增 precedence 属性,控制多样式表优先级。

    
    
    
  function ComponentWithStyle() {
  return (
    <>
      <link rel="stylesheet" href="styles.css" precedence="default" />
      <article>内容等样式加载完才显示</article>
    </>
  );
}

七、预加载 API 集合

React 19 提供四个显式预加载函数,放在组件顶层即可:


    
    
    
  import { prefetchDNS, preconnect, preload, preinit } from 'react-dom';

function AppRoot() {
  preinit('https://example.com/script.js', { as'script' });
  preload('https://example.com/font.woff', { as'font' });
  return <App />;
}

八、删除的 API(迁移清单)

| 被删 API | 替代方案 |
| | |
| propTypes | TypeScript |
| defaultProps | 函数默认参数 |
| contextTypes / getChildContext | Context.Provider |
| 字符串 ref | callback ref / createRef |
| createFactory | 直接 JSX |
| react-test-renderer/shallow | @testing-library/react |

九、Server Components 正式毕业

异步组件可在服务端直接跑,返回 HTML 给客户端。


    
    
    
  async function BlogPost({ id }) {
  const post = await db.posts.find(id);
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

目前完整支持需借助 Next.js、Remix 等全栈框架。

十、React Compiler(实验性):“告别手动 memo”

以前:


    
    
    
  const filtered = useMemo(() => todos.filter(...), [todos, filter]);
const handleClick = useCallback(id => {...}, []);

以后(开启 Compiler):


    
    
    
  const filtered = todos.filter(...);
const handleClick = id => {...};

编译器自动帮你做等值依赖分析,只在“真”变化时重新计算。
安装方式(独立插件):


    
    
    
  npm install babel-plugin-react-compiler

目前 Instagram 已全量上线,普通项目建议先灰度。

十一、Breaking Changes 速查

    1. 渲染阶段抛出的错误现在会被最近的 Error Boundary 捕获,不再静默打印。
    1. useEffect 的清理函数即使组件未挂载也会执行(与严格模式一致)。
    1. ref callback 在卸载时会收到 null,记得判空。

十二、要不要升级?官方建议

  • 新项目:直接上 React 19,享受 Actions + 新 Hooks。
  • 老项目:非强制,但升级成本不高;可先在一个分支验证 Compiler 收益。
  • Compiler可选且实验,生产环境请逐步灰度。

结语

React 19 没有颠覆式语法,却把“日常最烦人的异步状态”做成了官方范式,再加上 Compiler 的“自动 memo”,让业务代码几乎告别 useMemo/useCallback
如果你想体验“写完就下班”的快乐,现在就是最佳时机。