一文读懂React19究竟更新了什么
1. React Compiler 自动优化
编译阶段自动分析组件依赖关系,在底层自动插入useMemo、useCallback等效的缓存逻辑,无需开发者手动编写大量优化样板代码,彻底解决React 18时代的"优化疲劳"问题,同时避免依赖数组遗漏引发的性能bug。
2. use() Hook
打破传统Hooks必须在顶层调用的限制,支持在条件、分支逻辑中直接读取Promise或Context,异步数据获取写法更贴近同步逻辑,天然适配Suspense机制,大幅简化异步数据流的处理复杂度。 简单来说:传统的 Hooks(如 useState, useEffect)依赖"调用顺序"来维持状态,而 use() API 依赖"数据源本身的身份(Identity)"来维持状态。
function
// 传统 Hook: 必须在顶层
const [name, setName] = useState('');
// use() Hook: 可以在条件中
let data;
if (shouldFetch) {
// React 记录的是 "fetchUser(userId)" 返回的这个特定 Promise 对象
const promise = fetchUser(userId);
data = use(promise);
} else {
data = null;
}
return <div>{data?.name}</div>;
}
import
import ThemeContext from './ThemeContext';
function Button() {
// 可以在条件判断之后调用
if (someCondition) {
return null;
}
// 直接传入 Context 对象,无需 useContext
const theme = use(ThemeContext);
return <button style={{ color: theme.color }}>Click</button>;
}
核心变化解析 API 统一:use() 是一个多用途 API,它既可以处理 Promise(配合 Suspense),也可以处理 Context。当参数是 Context 对象时,它的行为等同于 useContext,但打破了 Hooks 的调用位置限制。 底层机制:use(Context) 和 useContext(Context) 在订阅 Context 变化和触发重渲染的机制上是一致的。当 Provider 的值更新时,使用了 use(Context) 的组件同样会重新渲染。 灵活性提升:这是 use() 读取 Context 的最大优势。在传统 React 中,如果你只想在特定条件下读取 Context,你依然必须在组件顶部调用 useContext,这有时会导致不必要的计算或代码结构不清晰。use() 允许你只在真正需要数据的地方才去读取它。
3. Actions 表单体系
新增useActionState、useOptimistic等API,原生支持直接绑定服务端函数,自动管理表单提交的Loading状态、错误信息和乐观更新效果,无需手动编写onSubmit、状态维护等冗余逻辑,表单开发效率显著提升。
import
import { Form, Input, Button } from 'antd';
// 1. 定义一个独立的子组件来使用 useFormStatus
function SubmitButton() {
const { pending } = useFormStatus();
return (
<Button
type="primary"
htmlType="submit"
loading={pending} // 利用 pending状态控制 Antd Button 的 loading效果
disabled={pending}
>
{pending ? '提交中...' : '提交'}
</Button>
);
}
// 2. 定义 Action 函数
async function myAction(formData) {
const data = Object.fromEntries(formData);
await new Promise(resolve => setTimeout(resolve, 2000)); // 模拟网络请求
console.log('Submitted:', data);
}
// 3. 主表单组件
export default function MyAntdForm() {
return (
<Form action={myAction}>
<Form.Item label="用户名" name="username">
<Input />
</Form.Item>
<Form.Item label="邮箱" name="email">
<Input />
</Form.Item>
{/* 4. 在 Form 内部使用子组件 */}
<Form.Item>
<SubmitButton />
</Form.Item>
</Form>
);
}
如果你直接在包含 <Form> 的同一个组件函数体内调用 useFormStatus,它将无法获取状态,因为 Hook 只能读取 父级 Form 的状态,而不能读取"同级"或"自身渲染"的 Form。 ⚠️ 注意:与 form.submit() 的区别
useFormStatus 监听的是原生表单的提交行为(即用户点击了 type="submit" 的按钮,或者触发了原生 submit 事件)。
- 适用场景 :你使用
<Form action={...}>这种 React 19 的新式声明式提交方式。 - 不适用场景 :如果你依然使用 Ant Design 传统的
onFinish+form.submit()编程式提交方式,useFormStatus可能不会按预期工作,因为它依赖于浏览器原生的表单提交生命周期。
如果你使用的是 Ant Design 传统的受控模式(不使用 action prop,而是用 onFinish),建议继续使用 Ant Design 自带的 buttonProps 或局部 state 来控制 loading 状态,或者迁移到 React 19 的 action 模式以享受 useFormStatus 的便利
4.原生Ref作为Prop支持
不再强制使用forwardRef,ref可作为普通属性直接在函数组件中通过props.ref接收,消除了额外的组件包装层级,简化TypeScript类型推导逻辑,统一了Ref的处理范式。
5.服务端组件原生支持
官方原生提供Server Components能力,组件可直接在服务端执行数据拉取逻辑,无需额外配置,大幅降低全栈React应用的开发门槛,同时减少客户端打包体积。