React 19 新特性全面解析:升级你的 React 应用!
React 19 现已稳定发布!自从 2024 年 4 月 React 19 RC 发布以来,加入了一些新特性和改进,已可通过 npm 或 yarn 安装更新!
// 使用 npm
npm install --save-exact react@^19.0.0 react-dom@^19.0.0
// 使用 yarn
yarn add --exact react@^19.0.0 react-dom@^19.0.0
// 如果你是使用 TypeScript,还需要更新一下类型
npm install --save-exact @types/react@^19.0.0 @types/react-dom@^19.0.0
yarn add --exact @types/react@^19.0.0 @types/react-dom@^19.0.0
React 19 中的新增功能与改进
异步状态管理
在 React 应用中,一个常见的场景是进行数据变更,并在数据变化后更新状态。比如,用户提交表单修改姓名时,通常需要发起 API 请求,并处理请求结果。在过去,你需要手动处理请求的挂起状态、错误、乐观更新等。
// Before Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const handleSubmit = async () => {
setIsPending(true);
const error = await updateName(name);
setIsPending(false);
if (error) {
setError(error);
return;
}
redirect("/path");
};
return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}
在 React 19 中,我们为过渡(transition)增加了对异步函数的支持,可以自动处理挂起状态、错误、表单以及乐观更新。例如,使用 [useTransition
]来自动管理请求的挂起状态。
// Using pending state from Actions
function UpdateName({}) {
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();
const handleSubmit = () => {
startTransition(async () => {
const error = await updateName(name);
if (error) {
setError(error);
return;
}
redirect("/path");
})
};
return (
<div>
<input value={name} onChange={(event) => setName(event.target.value)} />
<button onClick={handleSubmit} disabled={isPending}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
}
Actions 现在能够自动管理这些状态。它们不仅支持挂起状态,还支持乐观更新和错误处理,简化了开发过程。
在 React 19 中,上面的例子可以简化为:
// Using <form> Actions and useActionState
function ChangeName({ name, setName }) {
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
const error = await updateName(formData.get("name"));
if (error) {
return error;
}
redirect("/path");
return null;
},
null,
);
return (
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>Update</button>
{error && <p>{error}</p>}
</form>
);
}
新的 hook:useActionState
为了简化 Action 的常见用法,React 19 引入了新的 hook——useActionState
。该 hook 允许你管理 Action 的状态(如挂起状态、错误等),并返回最终的结果。
const [error, submitAction, isPending] = useActionState(
async (previousState, newName) => {
const error = await updateName(newName);
if (error) {
// You can return any result of the action.
// Here, we return only the error.
return error;
}
// handle success
return null;
},
null,
);
React DOM 新特性:<form>
和 [useFormStatus
]
React 19 将 [useFormStatus
] 引入到 <form>
组件中,便于组件在不需要层层传递 props 的情况下,访问表单的状态。此外,还可以通过 <form>
自动管理表单的提交和重置操作。
<form action={actionFunction}>
乐观更新:useOptimistic
在进行数据变更时,常常需要在请求完成之前乐观地展示最终状态。React 19 引入了 useOptimistic
,使得这种操作更加简单。通过该 hook,应用可以在请求处理中展示预期结果,待请求完成或失败时,再做相应的回退。
function ChangeName({currentName, onUpdateName}) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);
const submitAction = async formData => {
const newName = formData.get("name");
setOptimisticName(newName);
const updatedName = await updateName(newName);
onUpdateName(updatedName);
};
return (
<form action={submitAction}>
<p>Your name is: {optimisticName}</p>
<p>
<label>Change Name:</label>
<input
type="text"
name="name"
disabled={currentName !== optimisticName}
/>
</p>
</form>
);
}
新增 API:use
在 React 19 中,我们推出了 [use
] API,它允许你在渲染中读取资源(如 Promise)。React 会在资源解析完成之前暂停渲染,确保在数据准备好后再进行渲染。
import {use} from 'react';
function Comments({commentsPromise}) {
// `use` will suspend until the promise resolves.
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}
function Page({commentsPromise}) {
// When `use` suspends in Comments,
// this Suspense boundary will be shown.
return (
<Suspense fallback={<div>Loading...</div>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
)
}
静态 API:prerender 和 prerenderToNodeStream
React 19 新增了两个用于静态网站生成的 API,改进了 renderToString
,可以在静态 HTML 生成时等待数据加载,特别适合流式渲染环境,如 Node.js Streams 和 Web Streams。
import { prerender } from 'react-dom/static';
async function handler(request) {
const {prelude} = await prerender(<App />, {
bootstrapScripts: ['/main.js']
});
return new Response(prelude, {
headers: { 'content-type': 'text/html' },
});
}
React Server 组件
React 19 支持 React Server 组件,可以将一些组件在构建时预渲染或按需在服务器端运行,从而提高性能。这个功能使得全栈 React 架构得以支持并得到了稳定版本的引入。
React 19 改进亮点
ref 作为 prop
function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}
//...
<MyInput ref={ref} />
从 React 19 开始,函数组件可以直接使用 ref 作为 prop,而不再需要 forwardRef
。未来版本将会弃用 forwardRef
。
优化错误报告
React 19 改进了 hydration 错误的报告方式。现在,如果客户端渲染与服务器端渲染不匹配,React 会记录单一的错误信息,而不再重复抛出错误。
样式表支持
React 19 在样式表的处理上进行了优化,支持更好地管理样式表的加载顺序,避免样式表加载过慢导致页面渲染延迟。
function ComponentOne() {
return (
<Suspense fallback="loading...">
<link rel="stylesheet" href="foo" precedence="default" />
<link rel="stylesheet" href="bar" precedence="high" />
<article class="foo-class bar-class">
{...}
</article>
</Suspense>
)
}
function ComponentTwo() {
return (
<div>
<p>{...}</p>
<link rel="stylesheet" href="baz" precedence="default" /> <-- will be inserted between foo & bar
</div>
)
}
异步脚本支持
React 19 改善了异步脚本的渲染体验,支持在组件树中的任意位置渲染 async 脚本,并确保脚本不会重复加载。
function MyComponent() {
return (
<div>
<script async={true} src="..." />
Hello World
</div>
)
}
function App() {
<html>
<body>
<MyComponent>
...
<MyComponent> // won't lead to duplicate script in the DOM
</body>
</html>
}
资源预加载支持
React 19 引入了新的资源预加载 API,优化了初次加载和客户端更新的性能,能够提前加载需要的资源,提升页面响应速度。
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
function MyComponent() {
preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly
preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font
preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet
prefetchDNS('https://...') // when you may not actually request anything from this host
preconnect('https://...') // when you will request something but aren't sure what
}
兼容第三方脚本和扩展
通过改进 hydration 机制,React 19 可以更好地处理第三方脚本和浏览器扩展,避免它们引起的匹配错误。
更强大的错误处理
React 19 改进了错误处理机制,增加了 onCaughtError
、onUncaughtError
和 [onRecoverableError
]事件,以便开发者更灵活地处理不同类型的错误。
这个版本的 React 19 带来了许多令人兴奋的新特性与改进,无论是开发者体验,还是性能优化,都大大提升了 React 应用的效率和易用性。赶紧尝试升级你的项目吧!