React v19 稳定版现已正式发布。为了帮助用户更轻松地升级到 React 19,项目发布了与 18.2 相同的 react@18.3 版本,但添加了针对弃用 API 和 React 19 所需的其他更改的警告。官方建议先升级到 React 18.3.1,以帮助在升级到 React 19 之前识别问题。 一些更新内容具体包括: Actions 在 React 19 中,添加了在转换中使用异步函数的支持,以自动处理待处理状态、错误、表单和乐观更新。例如,用户可以使用 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> ); } 异步转换将立即将 isPending 状态设置为 true,发出异步请求,并在任何转换完成后将isPending切换回false。这样就可以在数据变更时保持当前 UI 的响应性和交互性。 在 Actions 的基础上,React 19 引入了 useOptimistic管理乐观更新的功能,以及一个全新的 Hook React.useActionState 用于处理常见的 Actions 场景。在 react-dom 中,添加了 <form> Actions 来自动管理表单,以及 useFormStatus 来支持表单中常见的 Actions 场景。 // 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 为了更简单的处理常见的 Actions 场景,添加了一个新的 Hook,称为 useActionState: 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, ); useActionState 接受一个函数(“Action”),并返回一个包装后的 Action 以供调用。当调用包装后的 Action 时,useActionState将返回Action的最后结果作为data,并返回Action的等待状态作为pending。 值得注意的是,在 Canary 版本中,React.useActionState以前被称为ReactDOM.useFormState,现在已将其重命名并弃用了useFormState。可参阅#28491 以了解更多信息。 React DOM: <form> Actions 在 React 19 中,Actions 被集成到了react-dom新引入的<form>功能中。现在支持将函数作为<form>、<input>和<button>元素的action和formAction属性传递,以使用 Actions 自动提交表单: <form action={actionFunction}> 当 <form>Action 成功执行时,React 会自动重置不受控组件的表单。如果需要手动重置 <form>,可以调用新的 React DOM APIrequestFormReset。 React DOM: New hook: useFormStatus 在设计系统中,通常需要编写设计组件,这些组件需要获取其所处 <form> 表单的相关信息,但又不想通过 props 逐级向下传递。虽然可以通过 Context 来实现这一点,但为了让这种常见情况更简单,React 19 添加了一个新 hookuseFormStatus: import {useFormStatus} from 'react-dom'; function DesignButton() { const {pending} = useFormStatus(); return <button type="submit" disabled={pending} /> } useFormStatus可以读取父级<form> 的状态,就好像该表单是一个 Context 提供者一样。 新 hook:useOptimistic 执行数据变更时的另一个常见 UI 模式是在异步请求进行时乐观地显示最终状态。在 React 19 中添加了一个新的 hookuseOptimistic 以使此操作更容易: 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> ); } 该 hook 将在 updateName 请求过程中立即渲染 optimisticName。当更新完成或出现错误时,React 将自动切换回 currentName 值。 New API: use 在 React 19 中,引入了一个新 API 来在渲染过程中读取资源:use。例如,可以使用 use 来读取一个 Promise,React 将挂起,直到 promise 成功解析: 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> ) } 还可以使用use来读取 Context,这使得你可以有条件地读取 Context,例如在提前返回之后读取: import {use} from 'react'; import ThemeContext from './ThemeContext' function Heading({children}) { if (children == null) { return null; } // This would not work with useContext // because of the early return. const theme = use(ThemeContext); return ( <h1 style={{color: theme.color}}> {children} </h1> ); } 该 useAPI 只能在渲染中调用,类似于 hooks。与 hooks 不同,use 可以有条件地调用。项目团队未来计划使用 use 支持更多在渲染中使用资源的方式。有关详细信息,可参阅文档 use。 新的 React DOM 静态 API 为 react-dom/static 添加了两个用于静态站点生成的新 API: prerender prerenderToNodeStream 这两个新的 API 通过等待数据加载以生成静态 HTML 来改进了renderToString。它们旨在与 Node.js Streams 和 Web Streams 等流式环境配合使用。例如,在 Web Stream 环境中,可以使用prerender将 React 组件树预渲染为静态 HTML: 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' }, }); } Prerender API 将等待所有数据加载完毕后再返回静态 HTML 流。流可以转换为字符串,或通过流式响应发送。它们不支持在加载时流式传输内容,而现有的 React DOM 服务端渲染 API 则支持此功能。可参阅 React DOM 静态 API。 更多详情可查看官方公告。 (责任编辑:IT) |