React v19

2024 年 12 月 5 日,由 React 團隊 發布


注意事項

React 19 現已穩定發布!

自本文於四月首次與 React 19 RC 分享以來新增的內容

本文的日期已更新以反映穩定版本發布日期。

React v19 現已在 npm 上可用!

在我們的 React 19 升級指南 中,我們分享了將應用程式升級到 React 19 的逐步說明。在本文中,我們將概述 React 19 的新功能,以及如何採用它們。

如需重大變更的清單,請參閱 升級指南


React 19 的新功能

動作

React 應用程式中一個常見的用例是執行資料變動,然後更新狀態以響應。例如,當使用者提交表單來更改其名稱時,您將發出 API 請求,然後處理響應。過去,您需要手動處理擱置狀態、錯誤、樂觀更新和循序請求。

例如,您可以在 useState 中處理擱置和錯誤狀態

// 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 中,我們新增了對在轉換中使用非同步函數的支持,以自動處理擱置狀態、錯誤、表單和樂觀更新。

例如,您可以使用 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 具有響應性和互動性。

注意事項

按照慣例,使用非同步轉換的函數稱為「動作」。

動作會自動為您管理提交資料

  • 擱置狀態:動作提供一個擱置狀態,該狀態在請求開始時啟動,並在提交最終狀態更新時自動重置。
  • 樂觀更新:動作支援新的 useOptimistic Hook,以便您在提交請求時向使用者顯示即時回饋。
  • 錯誤處理:動作提供錯誤處理,以便您可以在請求失敗時顯示錯誤邊界,並自動將樂觀更新還原為其原始值。
  • 表單<form> 元素現在支援將函數傳遞給 actionformAction props。將函數傳遞給 action props 預設使用動作,並在提交後自動重置表單。

在動作的基礎上,React 19 引入了 useOptimistic 來管理樂觀更新,以及一個新的 Hook React.useActionState 來處理動作的常見情況。在 react-dom 中,我們新增了 <form> 動作來自動管理表單,並使用 useFormStatus 來支援表單中動作的常見情況。

在 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>
);
}

在下一節中,我們將詳細介紹 React 19 中每個新的動作功能。

新的 Hook:useActionState

為了簡化 Actions 的常見使用案例,我們新增了一個名為 useActionState 的 Hook。

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 以供呼叫。這是可行的,因為 Actions 可以組合。當呼叫包裝後的 Action 時,useActionState 會將 Action 的最後結果作為 data 返回,并将 Action 的 pending 狀態作為 pending 返回。

注意事項

React.useActionState 在 Canary 版本中先前稱為 ReactDOM.useFormState,但我們已将其重新命名並棄用 useFormState

更多資訊,請參閱 #28491

如需更多資訊,請參閱 useActionState 的文件。

React DOM:<form> Actions

Actions 也與 React 19 react-dom 的新 <form> 功能整合。我們已新增支援將函式作為 <form><input><button> 元素的 actionformAction 屬性傳遞,以使用 Actions 自動提交表單。

<form action={actionFunction}>

<form> Action 成功時,React 會自動重設非受控組件的表單。如果您需要手動重設 <form>,可以呼叫新的 requestFormReset React DOM API。

如需更多資訊,請參閱 react-dom <form><input><button> 的文件。

React DOM:新的 Hook:useFormStatus

在設計系統中,撰寫需要存取其所在 <form> 相關資訊的設計組件是很常見的做法,而無需將屬性向下傳遞到組件。這可以透過 Context 來完成,但為了簡化常見案例,我們新增了一個名為 useFormStatus 的 Hook。

import {useFormStatus} from 'react-dom';

function DesignButton() {
const {pending} = useFormStatus();
return <button type="submit" disabled={pending} />
}

useFormStatus 讀取父 <form> 的狀態,如同表單是 Context 提供者一樣。

如需更多資訊,請參閱 react-domuseFormStatus 的文件。

新的 Hook:useOptimistic

執行資料變更時,另一個常見的 UI 模式是在非同步請求進行時,以樂觀的方式顯示最終狀態。在 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>
);
}

updateName 請求正在進行時,useOptimistic Hook 會立即渲染 optimisticName。更新完成或出錯時,React 會自動切換回 currentName 值。

如需更多資訊,請參閱 useOptimistic 的文件。

新的 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 不支援在渲染過程中建立的 Promise。

如果您嘗試將在渲染階段建立的 Promise 傳遞給 use,React 會發出警告

主控台
一個元件被未快取的 Promise 掛起。目前尚不支援在 Client Component 或 hook 中建立 Promise,除非透過相容 Suspense 的函式庫或框架。

要解決此問題,您需要從支援 Promise 快取的 Suspense 函式庫或框架傳遞 Promise。未來我們計劃發布功能,讓在渲染階段快取 Promise 更容易。

您也可以使用 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>
);
}

use API 只能在渲染階段呼叫,類似於 hooks。與 hooks 不同的是,use 可以有條件地呼叫。未來我們計劃支援更多方法,讓您可以在渲染階段使用 use 來使用資源。

更多資訊,請參閱 use 的文件。

新的 React DOM 靜態 API

我們在 react-dom/static 中新增了兩個新的 API,用於靜態網站生成

這些新的 API 改進了 renderToString,它們會等待資料載入以生成靜態 HTML。它們被設計用於串流環境,例如 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

React 伺服器元件 ...(svg 省略)

伺服器元件 ...(svg 省略)

伺服器元件是一種新的選項,允許在與用戶端應用程式或 SSR 伺服器不同的環境中,在打包之前提前渲染元件。這個獨立的環境是 React 伺服器元件中的「伺服器」。伺服器元件可以在建構時在您的 CI 伺服器上執行一次,或者可以使用網路伺服器針對每個請求執行。

React 19 包含了 Canary 版本中的所有 React 伺服器元件功能。這表示,提供伺服器元件的函式庫現在可以將 React 19 作為具有 react-server 匯出條件 的同儕相依性,以用於支援 全端 React 架構 的框架中。

注意事項

如何建構對伺服器元件的支援? ...(svg 省略)

雖然 React 19 中的 React 伺服器元件很穩定,並且在主要版本之間不會中斷,但用於實作 React 伺服器元件打包器或框架的底層 API 不遵循語義化版本控制,並且可能在 React 19.x 的次要版本之間中斷。

為了支援 React 伺服器元件作為打包器或框架,我們建議固定到特定 React 版本,或使用 Canary 版本。未來我們將繼續與打包器和框架合作,以穩定用於實作 React 伺服器元件的 API。

更多資訊,請參閱 React 伺服器元件 的文件。

伺服器動作 ...(svg 省略)

伺服器動作允許用戶端元件呼叫在伺服器上執行的非同步函式。

當使用 "use server" 指令定義伺服器動作時,您的框架會自動建立對伺服器函式的參考,並將該參考傳遞給用戶端元件。當在用戶端上呼叫該函式時,React 會向伺服器發送請求以執行該函式,並返回結果。

注意事項

伺服器元件沒有指令。 ...(svg 省略)

一個常見的誤解是,伺服器元件由 "use server" 表示,但伺服器元件沒有指令。"use server" 指令用於伺服器動作。

更多資訊,請參閱 指令 的文件。

可以在伺服器元件中建立伺服器動作,並將其作為 props 傳遞給用戶端元件,或者可以在用戶端元件中匯入和使用它們。

更多資訊,請參閱 React 伺服器動作 的文件。

React 19 的改進 ...(svg 省略)

將 `ref` 作為 prop 使用

從 React 19 開始,您現在可以將 `ref` 作為函式組件的 prop 進行訪問。

function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}

//...
<MyInput ref={ref} />

新的函式組件將不再需要 `forwardRef`,我們將發布一個程式碼修改工具,自動將您的組件更新為使用新的 `ref` prop。在未來的版本中,我們將棄用並移除 `forwardRef`。

注意事項

傳遞給類別的 `refs` 不會作為 prop 傳遞,因為它們引用的是組件實例。

水合錯誤的差異比較

我們還改進了 `react-dom` 中水合錯誤的錯誤報告。例如,以前在開發模式下會記錄多個錯誤,但沒有任何關於不匹配的資訊:

主控台
警告:文字內容不匹配。伺服器:「Server」 客戶端:「Client」 位於 span 位於 App
警告:水合過程中發生錯誤。伺服器 HTML 在 <div> 中被客戶端內容取代。
警告:文字內容不匹配。伺服器:「Server」 客戶端:「Client」 位於 span 位於 App
警告:水合過程中發生錯誤。伺服器 HTML 在 <div> 中被客戶端內容取代。
未捕獲錯誤:文字內容與伺服器渲染的 HTML 不匹配。 位於 checkForUnmatchedText

我們現在會記錄一條包含不匹配差異比較的訊息:

主控台
未捕獲錯誤:水合失敗,因為伺服器渲染的 HTML 與客戶端不匹配。因此,這棵樹將在客戶端重新生成。如果 SSR 處理的客戶端組件使用了以下內容,就可能發生這種情況: - 伺服器/客戶端分支 `if (typeof window !== 'undefined')`。 - 每次調用都會變化的變數輸入,例如 `Date.now()` 或 `Math.random()`。 - 使用者地區設定中的日期格式與伺服器不匹配。 - 外部變化的數據,沒有將其快照與 HTML 一起發送。 - 無效的 HTML 標籤嵌套。 如果客戶端安裝了在 React 加載之前干擾 HTML 的瀏覽器擴充功能,也可能發生這種情況。 https://react.dev.org.tw/link/hydration-mismatch <App> <span>+ Client- Server 位於 throwOnHydrationMismatch

將 `<Context>` 作為提供者使用

在 React 19 中,您可以將 `<Context>` 渲染為提供者,而不是 `<Context.Provider>`。

const ThemeContext = createContext('');

function App({children}) {
return (
<ThemeContext value="dark">
{children}
</ThemeContext>
);
}

新的 Context 提供者可以使用 `<Context>`,我們將發布一個程式碼修改工具來轉換現有的提供者。在未來的版本中,我們將棄用 `<Context.Provider>`。

Refs 的清理函式

我們現在支援從 `ref` 回調函式返回一個清理函式。

<input
ref={(ref) => {
// ref created

// NEW: return a cleanup function to reset
// the ref when element is removed from DOM.
return () => {
// ref cleanup
};
}}
/>

當組件卸載時,React 將調用從 `ref` 回調函式返回的清理函式。這適用於 DOM refs、指向類別組件的 refs 以及 `useImperativeHandle`。

注意事項

以前,React 會在卸載組件時使用 `null` 調用 `ref` 函式。如果您的 `ref` 返回一個清理函式,React 現在將跳過此步驟。

在未來的版本中,我們將棄用在卸載組件時使用 `null` 調用 refs 的做法。

由於引入了 ref 清理函式,從 `ref` 回調函式返回任何其他內容現在將被 TypeScript 拒絕。解決方法通常是停止使用隱式返回,例如:

- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />

原始程式碼返回了 `HTMLDivElement` 的實例,TypeScript 無法知道這是否 *應該* 是一個清理函式,或者您是否不想返回清理函式。

您可以使用 `no-implicit-ref-callback-return` 對此模式進行程式碼修改。

`useDeferredValue` 初始值

我們已在 `useDeferredValue` 中新增了一個 `initialValue` 選項。

function Search({deferredValue}) {
// On initial render the value is ''.
// Then a re-render is scheduled with the deferredValue.
const value = useDeferredValue(deferredValue, '');

return (
<Results query={value} />
);
}

當提供 initialValue 時,useDeferredValue 會在元件的初始渲染中將其作為 value 返回,並在背景中使用返回的 deferredValue 安排重新渲染。

更多資訊,請參閱 useDeferredValue

支援文件詮釋資料

在 HTML 中,文件詮釋資料標籤,例如 <title><link><meta>,保留用於放置在文件的 <head> 區段中。在 React 中,決定應用程式適用詮釋資料的元件可能與渲染 <head> 的位置相差甚遠,或者 React 根本不渲染 <head>。過去,這些元素需要在 effect 中手動插入,或者透過 react-helmet 等函式庫插入,並且在伺服器渲染 React 應用程式時需要小心處理。

在 React 19 中,我們新增了對在元件中原生渲染文件詮釋資料標籤的支援

function BlogPost({post}) {
return (
<article>
<h1>{post.title}</h1>
<title>{post.title}</title>
<meta name="author" content="Josh" />
<link rel="author" href="https://twitter.com/joshcstory/" />
<meta name="keywords" content={post.keywords} />
<p>
Eee equals em-see-squared...
</p>
</article>
);
}

當 React 渲染此元件時,它會看到 <title><link><meta> 標籤,並自動將它們提升到文件的 <head> 區段。透過原生支援這些詮釋資料標籤,我們能夠確保它們與僅限用戶端的應用程式、串流 SSR 和伺服器元件一起使用。

注意事項

您可能仍然需要詮釋資料函式庫

對於簡單的應用案例,將文件詮釋資料渲染為標籤可能就足夠了,但函式庫可以提供更強大的功能,例如根據目前的路由,使用特定詮釋資料覆蓋通用詮釋資料。這些功能讓 react-helmet 等框架和函式庫更容易支援詮釋資料標籤,而不是取代它們。

更多資訊,請參閱 <title><link><meta> 的文件。

支援樣式表

樣式表,包括外部連結的 (<link rel="stylesheet" href="...">) 和內嵌的 (<style>...</style>) 樣式表,由於樣式優先順序規則,需要在 DOM 中仔細定位。建構允許在元件內進行組合的樣式表功能很困難,因此使用者通常會將所有樣式載入到遠離可能依賴它們的元件的地方,或者使用封裝了這種複雜性的樣式函式庫。

在 React 19 中,我們正在解決這個複雜性問題,並透過內建的樣式表支援,更深入地整合到用戶端上的並行渲染和伺服器上的串流渲染。如果您告知 React 樣式表的 precedence(優先順序),它將管理樣式表在 DOM 中的插入順序,並確保在顯示依賴這些樣式規則的內容之前載入樣式表(如果它是外部的)。

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 會將樣式表包含在 <head> 中,這可確保瀏覽器在載入樣式表之前不會繪製任何內容。如果在我們開始串流之後才發現樣式表,React 將會確保在顯示依賴該樣式表的 Suspense 邊界內容之前,將樣式表插入到用戶端上的 <head> 中。

在用戶端渲染期間,React 將會等待新渲染的樣式表載入完成,再提交渲染。如果您在應用程式中的多個位置渲染此元件,React 將只會在文件中包含一次樣式表

function App() {
return <>
<ComponentOne />
...
<ComponentOne /> // won't lead to a duplicate stylesheet link in the DOM
</>
}

對於習慣手動載入樣式表的使用者來說,這是一個將這些樣式表與依賴它們的元件放在一起的機會,從而可以更好地進行局部推理,並且更容易確保只載入實際依賴的樣式表。

樣式函式庫和與打包器的樣式整合也可以採用這種新功能,因此即使您不直接渲染自己的樣式表,您仍然可以從工具升級以使用此功能中受益。

更多詳細資訊,請閱讀 <link><style> 的文件。

支援非同步腳本

在 HTML 中,一般腳本 (<script src="...">) 和延遲腳本 (<script defer="" src="...">) 按文件順序載入,這使得在元件樹的深處渲染這些腳本變得困難。然而,非同步腳本 (<script async="" src="...">) 將以任意順序載入。

在 React 19 中,我們透過允許您在元件樹中的任何位置、實際依賴腳本的元件內渲染非同步腳本,而無需管理腳本執行個體的重新定位和重複資料刪除,進一步支援非同步腳本。

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 只會載入和執行一次腳本,即使它是由多個不同的元件渲染的。

在伺服器端渲染中,非同步腳本將包含在 <head> 中,並排列在阻礙繪製的更重要資源(例如樣式表、字型和圖片預載入)之後。

如需更多詳細資訊,請閱讀 <script> 的文件。

支援預載資源

在初始文件載入和客戶端更新期間,盡早告知瀏覽器可能需要載入的資源,可以顯著影響頁面效能。

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
}
<!-- the above would result in the following DOM/HTML -->
<html>
<head>
<!-- links/scripts are prioritized by their utility to early loading, not call order -->
<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 可以透過將字體等額外資源的探索從樣式表載入中移出來,來最佳化初始頁面載入速度。它們還可以透過預先擷取預期導覽將使用的資源列表,然後在點擊甚至滑鼠懸停時立即預載這些資源,來加快客戶端更新速度。

更多詳細資訊,請參閱 資源預載 API

與第三方腳本和擴充功能的相容性

我們改進了水合作用 (hydration) 機制,以應對第三方腳本和瀏覽器擴充功能。

在水合作用過程中,如果在客戶端上渲染的元素與從伺服器接收的 HTML 中找到的元素不匹配,React 將強制客戶端重新渲染以修正內容。以前,如果第三方腳本或瀏覽器擴充功能插入了元素,則會觸發不匹配錯誤並進行客戶端渲染。

在 React 19 中,將會跳過 <head> 和 <body> 中的非預期標籤,避免不匹配錯誤。如果 React 需要由於不相關的水合作用不匹配而重新渲染整個文件,它將保留第三方腳本和瀏覽器擴充功能插入的樣式表。

更好的錯誤回報

我們在 React 19 中改進了錯誤處理,以消除重複並提供處理已捕獲和未捕獲錯誤的選項。例如,當錯誤邊界 (Error Boundary) 捕獲到渲染中的錯誤時,以前 React 會拋出兩次錯誤(一次針對原始錯誤,然後在自動恢復失敗後再次拋出),然後使用有關錯誤發生位置的資訊呼叫 console.error。

這導致每個捕獲的錯誤都會產生三個錯誤

主控台
未捕獲錯誤:hit at Throws at renderWithHooks
未捕獲錯誤:hit <-- 重複 at Throws at renderWithHooks
上述錯誤發生在 Throws 組件中 at Throws at ErrorBoundary 位於 App React 將嘗試使用您提供的錯誤邊界 ErrorBoundary 從頭開始重新建立此組件樹。

在 React 19 中,我們記錄一個包含所有錯誤資訊的單一錯誤

主控台
錯誤:hit at Throws at renderWithHooks 上述錯誤發生在 Throws 組件中 at Throws at ErrorBoundary 位於 App React 將嘗試使用您提供的錯誤邊界 ErrorBoundary 從頭開始重新建立此組件樹。 at ErrorBoundary 位於 App

此外,我們還添加了兩個新的根選項來補充 onRecoverableError

  • onCaughtError:當 React 在錯誤邊界中捕獲到錯誤時呼叫。
  • onUncaughtError:當拋出錯誤且未被錯誤邊界捕獲時呼叫。
  • onRecoverableError:當拋出錯誤並自動恢復時呼叫。

更多資訊和範例,請參閱 createRoot 和 hydrateRoot 的文件。

支援自訂元素 ...

React 19 增加了對自訂元素的完整支援,並通過了 Custom Elements Everywhere 上的所有測試。

在過去的版本中,在 React 中使用自訂元素一直很困難,因為 React 將無法識別的 props 視為屬性而不是特性。在 React 19 中,我們添加了對在客戶端和 SSR 期間有效的特性的支援,策略如下:

  • **伺服器端渲染**:如果傳遞給自訂元素的 props 類型是原始值(例如 string、number)或值為 true,則這些 props 將作為屬性渲染。具有非原始類型(例如 object、symbol、function)或值為 false 的 Props 將被省略。
  • **客戶端渲染**:與自訂元素實例上的特性匹配的 props 將被指定為特性,否則它們將被指定為屬性。

感謝 Joey Arhar 推動了 React 中自訂元素支援的設計和實作。

如何升級 ...

請參閱 React 19 升級指南,以取得逐步說明和完整的重大變更及重要變更列表。

注意:本文最初發佈於 2024 年 4 月 25 日,並已於 2024 年 12 月 5 日更新為穩定版本。