在AI时代,再去了解react19新特性还有用吗?
最近总有朋友问我:“现在AI写代码这么厉害了,我写个需求丢给cursor,chatgpt,各种ai大模型,几分钟页面逻辑全都有了,还学新特性干啥?直接让AI写不就完了?”
我通常会反问一句:“AI写的代码,你就不用担责了吗?是的,ai 不是人, 还承担不了岗位赋予你的责任, 而你为了这份责任,一定是用好ai, 控制ai, 直到它输出你想要的!”
即使最先进的AI,生成代码也可能有逻辑漏洞、性能坑,或者用了过时的API。而review AI代码、理解它为什么这么写、以及如何优化它,成了我们开发者新的核心竞争力。
所以,今天我们就以React 19的新特性为例,一起看看这些新玩意儿到底是什么,并且思考:如果你不懂它们,还停留在react16,17,18,那AI生成的代码里埋了坑,你能发现吗?
1. Actions:让数据提交像呼吸一样自然
先来看一个传统表单提交的痛点:
function OldForm() {
const [pending, setPending] = useState(false);
const [error, setError] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
setPending(true);
setError(null);
try {
const formData = new FormData(e.target);
await submitForm(formData);
} catch (err) {
setError(err.message);
} finally {
setPending(false);
}
};
return (
<form onSubmit={handleSubmit}>
<input name="name" />
<button type="submit" disabled={pending}>
{pending ? '提交中...' : '提交'}
</button>
{error && <p style={{color: 'red'}}>{error}</p>}
</form>
);
}
这段代码没什么大毛病,但每个表单都要重复写pending、error、try-catch,烦不烦?
React 19 的 Actions 直接内置了异步状态管理,用 useTransition 就能搞定:
import { useTransition } from 'react';
function NewForm() {
const [isPending, startTransition] = useTransition();
const [error, setError] = useState(null);
const action = async (formData) => {
startTransition(async () => {
try {
await submitForm(formData);
} catch (err) {
setError(err.message);
}
});
};
return (
<form action={action}>
<input name="name" />
<button type="submit" disabled={isPending}>
{isPending ? '提交中...' : '提交'}
</button>
{error && <p style={{color: 'red'}}>{error}</p>}
</form>
);
}
甚至还可以更简洁——用 useActionState(原 useFormState):
import { useActionState } from 'react';
async function submit(prevState, formData) {
try {
await submitForm(formData);
return { success: true, error: null };
} catch (err) {
return { success: false, error: err.message };
}
}
function SuperSimpleForm() {
const [state, formAction, isPending] = useActionState(submit, { success: false, error: null });
return (
<form action={formAction}>
<input name="name" />
<button type="submit" disabled={isPending}>
{isPending ? '提交中...' : '提交'}
</button>
{state.error && <p style={{color: 'red'}}>{state.error}</p>}
{state.success && <p style={{color: 'green'}}>提交成功!</p>}
</form>
);
}
AI可能犯的错:它可能还是用老式的useState+手动管理,或者忘记处理loading状态。如果你不了解Actions,就不知道AI生成的代码其实可以被简化成几行,并且性能更好(因为React能自动批处理更新)。
2. use API:条件语句里也能用“钩子”了
以前React有个铁律:Hooks不能在条件语句、循环里调用。这导致我们必须把所有context、状态提到组件最外层,哪怕有些数据只在特定分支需要。
React 19 引入了一个新API——use,它虽然名字像Hook,但可以在条件语句里用!
import { use, useContext } from 'react';
import { ThemeContext, UserContext } from './contexts';
function Profile({ userPromise }) {
// ✅ 可以在条件分支里用 use
if (userPromise) {
const user = use(userPromise); // 等待Promise
return <div>{user.name}</div>;
}
// ❌ 不能用useContext 因为它在 return 之后
// const theme = useContext(ThemeContext); // 报错!Hooks必须在顶层
// 但可以用 use 在条件里读取 Context
if (someCondition) {
const theme = use(ThemeContext);
return <div>主题:{theme}</div>;
}
return null;
}
有什么用?
- 结合Suspense,可以优雅地处理异步数据加载。
- 让你写出更灵活的组件,不再被“所有Hooks必须在顶层”束缚。
AI可能犯的错:它可能依然遵守老规则,把所有数据读取都提到顶部,导致组件性能变差。或者,它可能生成类似 if (user) { useContext(...) } 的代码,这在旧版React里直接报错。如果你不懂 use,就会觉得是AI写错了,但其实它是想用新特性。
3. <Activity> 组件:后台预渲染,页面切换如丝般顺滑
你有没有遇到过这样的场景:用户点了一个链接,新页面加载前会有短暂的空白,然后内容才蹦出来。如果能在用户悬停在链接上时,就偷偷把下一页渲染好,体验不就起飞了吗?
React 19.2 带来了 <Activity> 组件,它可以把一块UI标记为“后台活动”,让React在空闲时预渲染,同时保留它的所有状态。
import { Activity } from 'react';
import { useState } from 'react';
function App() {
const [showNext, setShowNext] = useState(false);
return (
<div>
<button onMouseEnter={() => setShowNext(true)}>
悬停预加载下一页
</button>
<Activity mode={showNext ? 'visible' : 'hidden'}>
<NextPage /> {/* 这个组件即使隐藏也在后台保持状态 */}
</Activity>
</div>
);
}
当 mode 是 'hidden' 时,<NextPage> 其实已经被渲染并挂载了,只是视觉上隐藏。用户点击跳转时,瞬间就能看到完整内容,零延迟。
AI可能犯的错:它可能还是用传统的懒加载+loading,或者用 display: none 简单隐藏组件,但那样不会预渲染,也不会保留状态。不懂 <Activity>,你就无法识别AI生成的体验优化方案有多“古老”。
4. 服务端渲染(SSR)的进化:部分预渲染(Partial Prerendering)
以前的服务端渲染(SSR)要么全静态(SSG),要么全动态(每次请求都重新渲染)。但很多页面是部分静态 + 部分动态的,比如电商详情页(商品描述静态,库存动态)。
React 19 通过 prerender + resume 实现了“部分预渲染”:
// 服务端代码
import { prerender, resume } from 'react-dom/server';
async function handleRequest(req, res) {
// 先预渲染静态部分,得到 HTML 和 一个 postponed 状态
const { html, postponed } = await prerender(<App page={req.url} />);
// 发送静态 HTML 给 CDN
res.send(html);
// 当真实用户请求时,用 postponed 继续渲染动态内容
const stream = await resume(<App page={req.url} />, postponed);
stream.pipe(res);
}
这样,静态部分可以缓存到CDN,动态部分在请求时才补全,首屏速度大幅提升。
AI可能犯的错:它可能还是用传统的 renderToString 全量渲染,或者笨拙地把所有内容都动态化。如果你不知道有 prerender,就可能放过性能优化的机会。
5. 开发者体验(DX)的温暖细节
5.1 useEffectEvent:告别依赖地狱
useEffect 里经常要依赖一些函数,但这些函数本身又依赖外部变量,导致依赖数组越来越长。React 19 提供了 useEffectEvent,让你把“事件型”逻辑分离出去,不再参与依赖追踪。
import { useEffect, useEffectEvent } from 'react';
function ChatRoom({ roomId, theme }) {
const onMessage = useEffectEvent((msg) => {
showNotification(theme, msg); // 这里依赖 theme,但不想因此重新订阅
});
useEffect(() => {
const connection = connect(roomId);
connection.on('message', onMessage);
return () => connection.disconnect();
}, [roomId]); // 依赖数组里不再需要 onMessage,因为它是事件
}
以前你必须用 useCallback 把 onMessage 包裹起来,并且把 theme 也加进依赖,导致订阅函数反复重建。现在用 useEffectEvent,一切优雅了。
AI可能犯的错:它可能依然生成一长串依赖,或者用 useCallback 勉强应付。如果你不懂这个新Hook,就不知道怎么优化。
5.2 性能追踪:Chrome DevTools 直接看 React 调度
在 React 19 里,打开 Chrome 的 Performance 面板,你可以看到 React 的自定义轨迹 —— 哪些任务是由 scheduler 调度的,哪个组件占用了多少时间。这简直是性能调优的神器。
以前我们只能靠 console.time 或者 React DevTools 的 Profiler,现在可以直接用浏览器原生工具分析。
AI可能犯的错:它可能写出性能极差的组件,但你看不出来,因为没有性能数据支撑。现在你可以用工具轻松发现瓶颈,并告诉 AI:“这里,重渲染太多了,优化一下。”
总结:AI 写代码,你懂新特性,才能当好“指挥官”
| 新特性 | 核心价值 | 不懂它,你可能错过什么 |
|---|---|---|
| Actions | 简化数据提交、loading、错误处理 | AI 生成一堆重复代码,你不知道可以用几行搞定 |
use | 条件分支里用“钩子”,更灵活 | AI 生成的组件可能报错,你不理解为什么 |
<Activity> | 后台预渲染,瞬时切换 | AI 的体验优化方案落后,用户感知不到流畅 |
| Partial Prerendering | 极速首屏,动静分离 | AI 可能让所有内容动态化,浪费资源 |
useEffectEvent | 消除依赖地狱,Effect 更干净 | AI 的 Effect 可能频繁重建,性能差 |
| 性能追踪 | 可视化调度,快速定位瓶颈 | AI 的性能问题你无法精确发现 |
AI 是强大的助手,但绝不是万能的代码审查员。 只有我们自己掌握了最新特性,才能在 AI 生成的代码里挑出毛病、指出优化方向,甚至手把手教 AI 写出更现代的代码。
所以,别停下学习的脚步。每学一个新特性,你就多了一把指挥 AI 的权杖。React 19 的这些更新,正是我们进化成“AI指挥官”的必修课。
你对哪个新特性最感兴趣?或者你在 review AI 代码时遇到过哪些奇葩问题?欢迎在评论区分享!