React 19 正式發(fā)布,看看該版本都帶來了那些更新!
12 月 6 日,React 19 正式發(fā)布,本文來看看該版本都帶來了那些更新!
React 19 更新內(nèi)容
Actions
Actions 是一種簡(jiǎn)化請(qǐng)求數(shù)據(jù)處理的方法統(tǒng)稱。
在 React 應(yīng)用中,一個(gè)很常見的用例是執(zhí)行數(shù)據(jù)變更,然后根據(jù)響應(yīng)更新狀態(tài)。例如,當(dāng)用戶提交表單以更改其姓名時(shí),需要發(fā)起 API 請(qǐng)求,并處理響應(yīng)結(jié)果。在過去,需要手動(dòng)處理等待狀態(tài)、錯(cuò)誤、樂觀更新以及順序請(qǐng)求等。
例如,可以使用 useState
來管理等待和錯(cuò)誤狀態(tài):
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 中,增加了對(duì)在轉(zhuǎn)換中使用異步函數(shù)的支持,以自動(dòng)處理等待狀態(tài)、錯(cuò)誤、表單和樂觀更新。
例如,可以使用useTransition
來自動(dòng)處理等待狀態(tài):
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>
);
}
異步轉(zhuǎn)換會(huì)立即將isPending
狀態(tài)設(shè)置為true
,發(fā)起異步請(qǐng)求,并在任何轉(zhuǎn)換完成后將isPending
切換回false
。這樣就可以在數(shù)據(jù)變更時(shí)保持當(dāng)前 UI 的響應(yīng)性和交互性。
在 React 19 中,基于 Actions 的概念,引入了useOptimistic
來管理樂觀更新,以及一個(gè)全新的 Hook React.useActionState
用于處理常見的 Actions 場(chǎng)景。在react-dom
中,添加了<form>
Actions 來自動(dòng)管理表單,以及useFormStatus
來支持表單中常見的 Actions 場(chǎng)景。
在 React 19 中,上面的例子可以簡(jiǎn)化為:
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
為了更簡(jiǎn)單的處理常見的 Actions 場(chǎng)景,React 19 引入了一個(gè)全新的 Hook useActionState
:
const [error, submitAction, isPending] = useActionState(
async (previousState, newName) => {
const error = await updateName(newName);
if (error) {
// 可以返回Action的任何結(jié)果
// 在這里,只返回錯(cuò)誤
return error;
}
// 處理成功情況
return null;
},
null,
);
useActionState
接受一個(gè)函數(shù)(即 Action),并返回一個(gè)包裝后的 Action 以供調(diào)用。當(dāng)調(diào)用包裝后的 Action 時(shí),useActionState
將返回Action
的最后結(jié)果作為data
,并返回Action
的等待狀態(tài)作為pending
。
React DOM: <form>
Actions
在 React 19 中,Actions 被集成到了 react-dom
新引入的 <form>
功能中?,F(xiàn)在支持將函數(shù)作為 <form>
、<input>
和 <button>
元素的 action
和 formAction
屬性傳遞,以使用 Actions 自動(dòng)提交表單:
<form action={actionFunction}>
當(dāng)<form>
相關(guān)的 Action 執(zhí)行成功時(shí),React 會(huì)自動(dòng)重置那些不受控組件的表單。如果需要手動(dòng)重置<form>
,可以調(diào)用新的 React DOM API requestFormReset
。
React DOM 全新 Hook:useFormStatus
在設(shè)計(jì)系統(tǒng)中,通常需要編寫設(shè)計(jì)組件,這些組件需要獲取其所處 <form>
表單的相關(guān)信息,但又不想通過 props
逐級(jí)向下傳遞。雖然可以通過 Context 來實(shí)現(xiàn)這一點(diǎn),但為了讓這種常見情況更簡(jiǎn)單,React 19 添加了一個(gè)全新的 Hook:useFormStatus
。
import {useFormStatus} from 'react-dom';
function DesignButton() {
const {pending} = useFormStatus();
return <button type="submit" disabled={pending} />
}
useFormStatus
可以讀取父級(jí)<form>
的狀態(tài),就好像該表單是一個(gè) Context 提供者一樣。
全新 Hook:useOptimistic
在執(zhí)行數(shù)據(jù)變更操作時(shí),另一種常見的 UI 模式是:在異步請(qǐng)求正在進(jìn)行的過程中,以樂觀的方式展示最終狀態(tài)。在 React 19 中,新增了一個(gè)名為useOptimistic
的 Hook,以簡(jiǎn)化這一過程:
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>
);
}
useOptimistic
Hook 將在 updateName
請(qǐng)求過程中立即渲染 optimisticName
。當(dāng)更新完成或出現(xiàn)錯(cuò)誤時(shí),React 將自動(dòng)切換回 currentName
值。
全新 API:use
在 React 19 中,引入了一個(gè)新 API 來在渲染過程中讀取資源:use
。
例如,可以使用 use
來讀取一個(gè) Promise,React 將掛起,直到promise
成功解析:
import {use} from 'react';
function Comments({commentsPromise}) {
// “use”會(huì)進(jìn)行“掛起”操作,直到“Promise”被成功解析。
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}
function Page({commentsPromise}) {
// 當(dāng)“Comments”組件中“use”進(jìn)行“掛起”操作時(shí),
// 這個(gè)“Suspense”邊界(組件)將會(huì)被顯示出來。
return (
<Suspense fallback={<div>Loading...</div>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
)
我們還可以使用 use
來讀取 Context,這使得你可以有條件地讀取 Context,例如在提前返回之后讀?。?/p>
import {use} from 'react';
import ThemeContext from './ThemeContext'
function Heading({children}) {
if (children == null) {
return null;
}
// 由于存在提前返回的情況,使用useContext是行不通的。
const theme = use(ThemeContext);
return (
<h1 style={{color: theme.color}}>
{children}
</h1>
);
}
use
API 只能在渲染過程中調(diào)用,類似于 Hooks。與 Hooks 不同的是,use
可以有條件地調(diào)用。未來計(jì)劃支持更多使用 use
在渲染過程中消費(fèi)資源的方式。
新的 React DOM 靜態(tài) API
React 19 為react-dom/static
添加了兩個(gè)新的 API,用于靜態(tài)網(wǎng)站生成:
prerender
prerenderToNodeStream
這兩個(gè)新 API 改進(jìn)了 renderToString
,通過等待數(shù)據(jù)加載來生成靜態(tài) HTML。它們被設(shè)計(jì)為與流環(huán)境(如 Node.js Streams 和 Web Streams)一起工作。例如,在 Web Stream 環(huán)境中,可以使用 prerender
將 React 組件樹預(yù)渲染為靜態(tài) 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 會(huì)在返回靜態(tài) HTML 流之前等待所有數(shù)據(jù)加載完成。流可以被轉(zhuǎn)換為字符串,或者通過流式響應(yīng)進(jìn)行發(fā)送。它們不支持在加載內(nèi)容時(shí)進(jìn)行流式傳輸,而現(xiàn)有的 React DOM 服務(wù)端渲染 API 是支持這種流式傳輸?shù)摹?/p>
React Server Components
服務(wù)器組件
服務(wù)器組件是一個(gè)新的選項(xiàng),它允許在打包之前,在與客戶應(yīng)用或服務(wù)端渲染(SSR)服務(wù)器分離的環(huán)境中預(yù)先渲染組件。這個(gè)分離的環(huán)境就是 React 服務(wù)器組件中的“服務(wù)器”。服務(wù)器組件既可以在持續(xù)集成(CI)服務(wù)器上構(gòu)建時(shí)運(yùn)行一次,也可以在使用Web服務(wù)器時(shí)針對(duì)每個(gè)請(qǐng)求運(yùn)行。
React 19 包含了從 Canary 版本引入的所有 React 服務(wù)器組件功能。這意味著,現(xiàn)在提供服務(wù)器組件的庫(kù)可以將 React 19 作為對(duì)等依賴項(xiàng),并使用 react-server
導(dǎo)出條件,以便在支持全棧 React 架構(gòu)的框架中使用。
服務(wù)器 Actions
服務(wù)器 Actions 允許客戶端組件調(diào)用在服務(wù)器上執(zhí)行的異步函數(shù)。
當(dāng)使用 “use server” 指令定義一個(gè)服務(wù)端 Actions 時(shí),框架會(huì)自動(dòng)創(chuàng)建一個(gè)指向服務(wù)器函數(shù)的引用,并將這個(gè)引用傳遞給客戶端組件。當(dāng)客戶端調(diào)用這個(gè)函數(shù)時(shí),React 會(huì)發(fā)送一個(gè)請(qǐng)求到服務(wù)器執(zhí)行該函數(shù),并返回結(jié)果。
服務(wù)器 Actions 可以在服務(wù)器組件中創(chuàng)建,并通過 props
傳遞給客戶端組件,也可以被導(dǎo)入并在客戶端組件中使用。
其他更新
ref 作為 prop
從 React 19 開始,可以在函數(shù)組件中通過 prop
訪問 ref
:
function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}
//...
<MyInput ref={ref} />
新的函數(shù)組件將不再需要 forwardRef
,React 團(tuán)隊(duì)將發(fā)布一個(gè)代碼轉(zhuǎn)換工具(codemod),以自動(dòng)更新組件,使其使用新的 ref
prop。在以后的版本中,將棄用并移除 forwardRef
。
水合錯(cuò)誤的差異信息展示
React 19 還改進(jìn)了 react-dom 中針對(duì)水合錯(cuò)誤的報(bào)錯(cuò)報(bào)告。例如,之前在開發(fā)環(huán)境(DEV)中,并不會(huì)展示任何關(guān)于不匹配情況的信息,而是記錄多個(gè)錯(cuò)誤;
現(xiàn)在,改為記錄一條包含不匹配差異信息的消息:
作為提供者
在 React 19 中,可以將<Context>
作為提供者,而不必使用<Context.Provider>
:
const ThemeContext = createContext('');
function App({children}) {
return (
<ThemeContext value="dark">
{children}
</ThemeContext>
);
}
新的 Context 提供者可以使用 <Context>
,React 團(tuán)隊(duì)將發(fā)布一個(gè)代碼轉(zhuǎn)換工具(codemod)來轉(zhuǎn)換現(xiàn)有的提供者。在未來的版本中,將棄用 <Context.Provider>
。
refs 的清理函數(shù)
在 React 19 中,支持從 ref
的回調(diào)函數(shù)中返回一個(gè)清理函數(shù):
<input
ref={(ref) => {
// 引用已創(chuàng)建
// 新增:返回一個(gè)清理函數(shù),以便在元素從DOM中移除時(shí)重置引用。
return () => {
// 執(zhí)行引用清理操作
};
}}
/>
當(dāng)組件卸載時(shí),React 會(huì)調(diào)用從 ref
回調(diào)函數(shù)中返回的清理函數(shù)。這適用于 DOM 引用、指向類組件的引用以及useImperativeHandle
的情況。
由于引入了 ref 清理函數(shù),現(xiàn)在從 ref 回調(diào)函數(shù)中返回其他任何內(nèi)容都會(huì)被 TypeScript 拒絕。解決辦法通常是停止使用隱式返回,例如:
- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />
原代碼返回了HTMLDivElement
的實(shí)例,而 TypeScript 無法判斷這是否是一個(gè)清理函數(shù),或者你并不想返回清理函數(shù)。
useDeferredValue 初始值
在 React 19 中,為useDeferredValue
添加了一個(gè)initialValue
選項(xiàng):
function Search({deferredValue}) {
// 在初始渲染時(shí),值為 ''
// 然后會(huì)基于 deferredValue 進(jìn)行重新渲染
const value = useDeferredValue(deferredValue, '');
return (
<Results query={value} />
);
}
當(dāng)提供 initialValue
時(shí),useDeferredValue
將在組件的初始渲染中將其作為值返回,并在后臺(tái)計(jì)劃用返回的 deferredValue
進(jìn)行重新渲染。
支持文檔元數(shù)據(jù)
在HTML文檔中,諸如<title>
、<link>
和<meta>
等元數(shù)據(jù)標(biāo)簽通常被專門放置在<head>
部分。然而,在 React 中,確定并應(yīng)用恰當(dāng)?shù)脑獢?shù)據(jù)可能會(huì)變得復(fù)雜,因?yàn)檫@些組件可能遠(yuǎn)離實(shí)際渲染<head>
標(biāo)簽的位置,甚至 React 本身可能并不直接渲染<head>
。過去,這些元素需要在副作用中手動(dòng)插入,或者通過像 react-helmet 這樣的庫(kù)來處理,并且在服務(wù)端渲染 React 應(yīng)用時(shí)需要小心處理。
在 React 19 中,增加了對(duì)在組件中原生渲染文檔元數(shù)據(jù)標(biāo)簽的支持:
function BlogPost({post}) {
return (
<article>
<h1>{post.title}</h1>
<title>{post.title}</title>
<meta name="author" content="Josh" />
<link rel="author" />
<meta name="keywords" content={post.keywords} />
<p>
Eee equals em-see-squared...
</p>
</article>
);
}
當(dāng) React 渲染這個(gè)組件時(shí),它會(huì)識(shí)別 <title>
、<link>
和 <meta>
標(biāo)簽,并自動(dòng)將它們提升到文檔的 <head>
部分。通過原生支持這些元數(shù)據(jù)標(biāo)簽,能夠確保它們?cè)趦H限客戶端應(yīng)用、流式服務(wù)端渲染和服務(wù)器組件中正常工作。
樣式表支持
無論是外部鏈接的樣式表(如<link rel="stylesheet" href="...">
)還是內(nèi)聯(lián)樣式表(如<style>...</style>
),由于樣式優(yōu)先級(jí)規(guī)則的存在,它們?cè)?DOM 中的放置位置都需要謹(jǐn)慎。構(gòu)建一個(gè)允許在組件內(nèi)部進(jìn)行組合的樣式表功能是很困難的,所以用戶往往要么將所有樣式加載到距離可能依賴它們的組件很遠(yuǎn)的地方,要么使用封裝了這種復(fù)雜性的樣式庫(kù)。
在 React 19 中,解決了這種復(fù)雜性,并通過內(nèi)置對(duì)樣式表的支持,在客戶端的并發(fā)渲染以及服務(wù)端流式渲染方面實(shí)現(xiàn)更深入的集成。如果你告知 React 樣式表的優(yōu)先級(jí),它將會(huì)管理樣式表在 DOM 中的插入順序,并確保樣式表(如果是外部樣式表的話)在顯示依賴于這些樣式規(guī)則的內(nèi)容之前加載該樣式表。
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" /> <!-- 將被插入到 foo 和 bar 之間 -->
</div>
)
}
在服務(wù)端渲染期間,React 將把樣式表包含在 <head>
中,這確保了瀏覽器在加載完成后才會(huì)繪制。如果在開始流式傳輸后發(fā)現(xiàn)樣式表,React 將確保在客戶端的 <head>
中插入樣式表,然后才顯示依賴于該樣式表的 Suspense 邊界的內(nèi)容。
在客戶端渲染期間,React 將等待新渲染的樣式表加載完成后再提交渲染。如果在應(yīng)用的多個(gè)地方渲染這個(gè)組件,React 將只在文檔中包含一次樣式表:
function App() {
return <>
<ComponentOne />
...
<ComponentOne /> // 不會(huì)導(dǎo)致 DOM 中出現(xiàn)重復(fù)的樣式表鏈接
</>
}
對(duì)于習(xí)慣于手動(dòng)加載樣式表的用戶來說,這是一個(gè)將樣式表放置在依賴它們的組件旁邊的好機(jī)會(huì),這樣能更便于局部分析,也更容易確保只加載實(shí)際依賴的樣式表。
樣式庫(kù)和與打包工具的樣式集成也可以采用這一功能,因此即使不直接渲染自己的樣式表,當(dāng)使用的工具升級(jí)以使用該功能時(shí),仍然可以從中受益。
支持異步腳本
在 HTML 中,普通腳本(<script src="...">
)和延遲腳本(<script defer="" src="...">
)按照文檔順序加載,這使得在組件樹的深處渲染這些類型的腳本變得具有挑戰(zhàn)性。然而,異步腳本(<script async="" src="...">
)會(huì)以任意順序加載。
在 React 19 中,通過允許在組件樹的任意位置渲染異步腳本,提供了對(duì)異步腳本更好的支持,即在實(shí)際依賴該腳本的組件內(nèi)部渲染它們,而無需管理腳本實(shí)例的重新定位和去重。
function MyComponent() {
return (
<div>
<script async={true} src="..." />
Hello World
</div>
);
}
function App() {
return (
<html>
<body>
<MyComponent>
...
<MyComponent> // 不會(huì)導(dǎo)致DOM中出現(xiàn)重復(fù)的腳本
</body>
</html>
);
}
在所有的渲染環(huán)境中,異步腳本都會(huì)進(jìn)行去重處理,所以即便它被多個(gè)不同的組件渲染,React 也只會(huì)加載并執(zhí)行該腳本一次。
在服務(wù)端渲染過程中,異步腳本會(huì)被包含在<head>
部分,并優(yōu)先級(jí)排在更關(guān)鍵的資源之后,這些資源會(huì)阻塞繪制,如樣式表、字體和圖片預(yù)加載。
支持預(yù)加載資源
在初始文檔加載以及客戶端更新期間,盡早告知瀏覽器它可能需要加載的資源,會(huì)對(duì)頁面性能產(chǎn)生顯著的影響。
React 19 包含了許多用于加載和預(yù)加載瀏覽器資源的新 API,旨在盡可能簡(jiǎn)便地打造優(yōu)質(zhì)的用戶體驗(yàn),避免因資源加載效率低下而受到影響。
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom';
function MyComponent() {
preinit('https://.../path/to/some/script.js', { as: 'script' }); // 積極加載并執(zhí)行此腳本
preload('https://.../path/to/font.woff', { as: 'font' }); // 預(yù)加載此字體
preload('https://.../path/to/stylesheet.css', { as: 'style' }); // 預(yù)加載此樣式表
prefetchDNS('https://...'); // 當(dāng)你實(shí)際上可能不會(huì)從此主機(jī)請(qǐng)求任何內(nèi)容時(shí)
preconnect('https://...'); // 當(dāng)你將請(qǐng)求某些內(nèi)容但不確定是什么時(shí)
}
<html>
<head>
<!-- 鏈接/腳本根據(jù)其對(duì)早期加載的有用性進(jìn)行優(yōu)先級(jí)排序,而不是調(diào)用順序 -->
<link rel="prefetch-dns" href="https://...">
<link rel="preconnect" href="https://...">
<link rel="preload" as="font" href="https://.../path/to/font.woff">
<link rel="preload" as="style" href="https://.../path/to/stylesheet.css">
<script async="" src="https://.../path/to/some/script.js"></script>
</head>
<body>
...
</body>
</html>
這些 API 可用于優(yōu)化初始頁面加載,比如將字體等額外資源的發(fā)現(xiàn)過程從樣式表加載環(huán)節(jié)中分離出來。它們還能通過預(yù)取預(yù)期導(dǎo)航將會(huì)用到的資源列表,然后在點(diǎn)擊甚至懸停操作時(shí)就立即預(yù)加載這些資源,從而加快客戶端更新的速度。
與第三方腳本和擴(kuò)展的兼容性
在 React 19 中,改進(jìn)了 hydration(水合,即客戶端激活)以適應(yīng)第三方腳本和瀏覽器擴(kuò)展。
在水合過程中,如果在客戶端渲染的元素與服務(wù)端生成的 HTML 中的元素不匹配,React 將強(qiáng)制客戶端重新渲染以修正內(nèi)容。以前,如果元素是由第三方腳本或?yàn)g覽器擴(kuò)展插入的,它將觸發(fā)不匹配錯(cuò)誤并導(dǎo)致客戶端重新渲染。
在 React 19 中,<head>
和 <body>
中的意外標(biāo)簽將被跳過,避免了不匹配錯(cuò)誤。如果 React 需要由于與水合不相關(guān)的錯(cuò)誤而重新渲染整個(gè)文檔,它將保留由第三方腳本和瀏覽器擴(kuò)展插入的樣式表。
更好的錯(cuò)誤報(bào)告
React 19 中改進(jìn)了錯(cuò)誤處理,以消除重復(fù)并提供處理捕獲和未捕獲錯(cuò)誤的選項(xiàng)。例如,當(dāng)渲染過程中出現(xiàn)錯(cuò)誤并被 Error Boundary 捕獲時(shí),以前 React 會(huì)拋出錯(cuò)誤兩次(一次是原始錯(cuò)誤,然后是在嘗試自動(dòng)恢復(fù)失敗后再次拋出),然后調(diào)用 console.error
顯示錯(cuò)誤發(fā)生位置的信息。
這導(dǎo)致每個(gè)捕獲的錯(cuò)誤都有三個(gè)錯(cuò)誤:
在 React 19 中,只會(huì)記錄一個(gè)包含所有錯(cuò)誤信息的單一錯(cuò)誤:
在 React 19 中,引入了三個(gè)新的根選項(xiàng)來補(bǔ)充 onRecoverableError:
- onCaughtError:當(dāng) React 在 Error Boundary 中捕獲錯(cuò)誤時(shí)調(diào)用。
- onUncaughtError:當(dāng)拋出錯(cuò)誤并且未被 Error Boundary 捕獲時(shí)調(diào)用。
- onRecoverableError:當(dāng)拋出錯(cuò)誤并自動(dòng)恢復(fù)時(shí)調(diào)用。
支持自定義元素
React 19 增加了對(duì)自定義元素的完整支持,并通過了Custom Elements Everywhere的所有測(cè)試。
在以前的版本中,由于 React 將未識(shí)別的 props 視為 HTML 屬性而不是 JavaScript 屬性,所以在 React 中使用自定義元素一直很困難。在 React 19 中,增加了對(duì) JS 屬性的支持,這在客戶端和服務(wù)端渲染(SSR)中都有效,具體策略如下:
- 服務(wù)端渲染:傳遞給自定義元素的 props 如果是原始值類型,如字符串、數(shù)字,或者值為 true,它們將作為 HTML 屬性渲染。具有非原始值類型(如對(duì)象、符號(hào)、函數(shù))或值為 false的 props 將被省略。
- 客戶端渲染:與自定義元素實(shí)例上的屬性匹配的 props 將被分配為 JS 屬性,否則它們將被分配為 HTML 屬性。
React 19 更新總結(jié)
- Actions:
useActionState
Hook:接受一個(gè)函數(shù)(Action),返回包裝后的 Action 供調(diào)用,調(diào)用時(shí)返回結(jié)果和等待狀態(tài),用于簡(jiǎn)化常見的 Actions 場(chǎng)景處理。useOptimistic
Hook:在執(zhí)行數(shù)據(jù)變更的異步請(qǐng)求時(shí),以樂觀方式展示最終狀態(tài),更新完成或出錯(cuò)后自動(dòng)切換回原值,優(yōu)化用戶界面反饋。<form>
Actions 集成:在react-dom
中,支持將函數(shù)作為<form>
、<input>
和<button>
元素的相關(guān)屬性傳遞,實(shí)現(xiàn)自動(dòng)提交表單,成功時(shí)自動(dòng)重置不受控組件表單,也可手動(dòng)調(diào)用requestFormReset
API 重置。useFormStatus
Hook:方便編寫設(shè)計(jì)組件獲取所處<form>
表單信息,無需層層傳遞props
,可像讀取 Context 提供者狀態(tài)一樣讀取表單狀態(tài)。
use
API:用于在渲染時(shí)讀取資源,可讀取Promise
并讓 React 掛起直至其解析,也能讀取Context
,且可條件性調(diào)用。- 新的 React DOM 靜態(tài) API:
prerender
和prerenderToNodeStream
用于靜態(tài)網(wǎng)站生成,改進(jìn)renderToString
功能,會(huì)等待數(shù)據(jù)加載后生成靜態(tài) HTML,適配 Node.js Streams 和 Web Streams 等流環(huán)境。 - React Server Components:提供在獨(dú)立于客戶端應(yīng)用或 SSR 服務(wù)器環(huán)境中提前渲染組件的新選擇,相關(guān)庫(kù)可將 React 19 作為對(duì)等依賴,應(yīng)用于支持全棧 React 架構(gòu)的框架。
ref
作為 prop:現(xiàn)在可以在函數(shù)組件中直接使用ref
作為prop
。- 水合錯(cuò)誤改進(jìn):改進(jìn)了客戶端渲染和服務(wù)端渲染之間的水合錯(cuò)誤報(bào)告。
<Context>
作為提供者:可以直接使用<Context>
作為提供者,而不是<Context.Provider>
。- ref 的清理函數(shù):現(xiàn)在可以從
ref
回調(diào)中返回一個(gè)清理函數(shù)。 useDeferredValue
的初始值:為useDeferredValue
添加了initialValue
選項(xiàng)。- 文檔元數(shù)據(jù)支持:支持在組件中渲染
<title>
、<link>
和<meta>
標(biāo)簽,并自動(dòng)提升到文檔的<head>
部分。 - 樣式表支持:提供了對(duì)樣式表的內(nèi)置支持,包括外部鏈接和內(nèi)聯(lián)樣式。
- 異步腳本支持:改進(jìn)了對(duì)異步腳本的支持,允許在組件樹的任何位置渲染它們。
- 資源預(yù)加載支持:包括
prefetchDNS
、preconnect
、preload
和preinit
等 API,用于優(yōu)化資源加載。 - 與第三方腳本和擴(kuò)展的兼容性:改進(jìn)了水合以適應(yīng)第三方腳本和瀏覽器擴(kuò)展。
- 更好的錯(cuò)誤報(bào)告:改進(jìn)了錯(cuò)誤處理,減少了重復(fù)錯(cuò)誤,并提供了處理捕獲和未捕獲錯(cuò)誤的選項(xiàng)。
- 對(duì)自定義元素的支持:增加了對(duì)自定義元素的全面支持。