作為 WordPress 開發人員,我們經常將自定義的 React 元件整合到我們的主題和外掛中,以建立動態和響應式的使用者介面。
隨著 React 19 的即將釋出,為可能影響我們現有程式碼庫的更改和棄用做好準備至關重要。將於 7 月 16 日釋出的 WordPress 6.6 包含 React 18.3。該版本與 18.2 幾乎完全相同,但增加了對已廢棄功能的警告,以幫助您為 React 19 做好準備。
解決這些棄用問題對於確保與 React 19 的相容性至關重要,忽略它們可能會在 React 19 釋出幷包含在 WordPress 中時,導致您的自定義區塊、外掛或主題出現錯誤或問題。
本文概述了每種棄用情況,提供了程式碼示例,並指導您替換棄用的功能,以保持功能的流暢性。
注:為了幫助進行升級,React 團隊與 Codemod 團隊合作釋出了一些 codemods,它們會自動將您的程式碼更新為 React 19 中的許多新 API 和模式。
所有的 codemod 都可以在 GitHub 上的 react-codemod repo 中找到。此外,我們還將附上每個棄用程式碼的 codemod 命令(如果可用),以幫助您自動更新程式碼。
React 中已刪除的棄用功能
為了精簡 React 庫並鼓勵最佳實踐,我們刪除了一些已廢棄的 API 和功能。本節將介紹主要更改以及如何相應地更新程式碼。
1. 移除函式元件的 defaultProps
React 19 將移除函式元件的 defaultProps
,轉而使用 ES6 預設引數。根據 WordPress 團隊的說法,這種棄用最常用於外掛和主題中。
作為 WordPress 開發人員,您可能會使用 defaultProps
為函式元件中的道具提供預設值,以確保即使沒有傳遞某些道具,元件也能正常執行。
以下是使用 defaultProps
後的當前程式碼:
function CustomButton({ label, color }) { return <button style={{ backgroundColor: color }}>{ label }</button>; } CustomButton.defaultProps = { label: 'Click me', color: 'blue', };
在本示例中,CustomButton
元件的預設 label
和 color
值由 defaultProps
提供。在 React 19 中,這將引發一個警告錯誤,提醒您使用 ES6 預設引數。
以下是使用 ES6 預設引數的更新程式碼:
function CustomButton({ label = 'Click me', color = 'blue' }) { return <button style={{ backgroundColor: color }}>{ label }</button>; }
使用 ES6 預設引數,預設值現在直接出現在函式簽名中,使程式碼更易於閱讀和維護。
2. 移除函式元件的 propTypes
propTypes
已在 React 15.5.0 中被棄用,並將在 v19 版本的 React 包中完全移除。如果您正在使用 propTypes
,建議遷移到 TypeScript 或其他型別檢查解決方案。
您可能一直在使用 propTypes
來驗證傳遞給函式元件的道具,以確保它們接收到正確的型別和值。例如:
import PropTypes from 'prop-types'; function CustomButton({ label, color }) { return <button style={{ backgroundColor: color }}>{ label }</button>; } CustomButton.defaultProps = { label: 'Click me', color: 'blue', }; CustomButton.propTypes = { label: PropTypes.string, color: PropTypes.string, };
如今,您可以開始使用 TypeScript 進行這些型別檢查:
type CustomButtonProps = { label?: string; color?: string; }; const CustomButton = ({ label = 'Click me', color = 'blue' }: CustomButtonProps) => { return <button style={{ backgroundColor: color }}>{ label }</button>; };
注:為了幫助您從使用 propTypes
切換到 TypeScript,您可以使用以下 codemod 命令:
npx codemod@latest react/prop-types-typescript
3. 移除傳統上下文(contextTypes 和 getChildContext)
鑑於 WordPress 中許多外掛和程式碼庫的長期存在,您可能仍在您的類元件中使用傳統的 contextTypes
和 getChildContext
API。這些應用程式介面用於將資料從父元件傳遞到其子元件,而無需在每個層級明確傳遞道具。
不過,值得注意的是,傳統上下文已在 React 16.6.0 中被棄用,並將在 React v19 中移除。這一改動的目的是讓 React 稍微更小更快,因為傳統 Context API 有一些細微的 bug,經常容易被忽視。
傳統方法已被新的 contextType
API 所取代。
下面是一個示例,說明您如何在 WordPress 外掛中使用已廢棄的 Context API,將全域性設定(如網站標題)從父元件傳遞到子元件,而無需進行道具鑽取:
import PropTypes from 'prop-types'; class SettingsProvider extends React.Component { static childContextTypes = { siteTitle: PropTypes.string.isRequired, }; getChildContext() { return { siteTitle: 'My WordPress Site' }; } render() { return <SettingsConsumer />; } } class SettingsConsumer extends React.Component { static contextTypes = { siteTitle: PropTypes.string.isRequired, }; render() { return <div>Site Title: {this.context.siteTitle}</div>; } }
相比之下,現代方法使用 createContext
方法。在準備 React 19 時,您應該採用這種方法:
import React from 'react'; const SettingsContext = React.createContext(); class SettingsProvider extends React.Component { render() { return ( <SettingsContext value={{ siteTitle: 'My WordPress Site' }}> <SettingsConsumer /> </SettingsContext> ); } } class SettingsConsumer extends React.Component { static contextType = SettingsContext; render() { const { siteTitle } = this.context; return <div>Site Title: { siteTitle }</div>; } }
4. 移除字串引用
使用字串引用曾是在 React 元件中訪問 DOM 元素的常用方法。不過,自 React 16.3.0 以來,這種方法一直被視為傳統方法,並將在 v19 中移除。
字串引用雖然簡單明瞭,但也存在一些問題,例如潛在的命名衝突和缺乏靈活性。
請看一個在 WordPress 自定義塊中使用字串引用的例子。想象一下,您有一個包含輸入框的 Gutenberg 自定義區塊,您希望在將該區塊新增到編輯器時自動聚焦輸入框。下面是您如何使用字串引用來實現這一目的:
class CustomBlock extends React.Component { componentDidMount() { this.refs.input.focus(); } render() { return <input ref="input" placeholder="Enter text..." />; } }
要為 React 19 做好準備,您必須使用回撥 ref
或 React.createRef
API 替換字串 ref。下面是使用回撥 ref
的相同示例:
class CustomBlock extends React.Component { componentDidMount() { this.input.focus(); } render() { return <input ref={(input) => (this.input = input)} placeholder="Enter text..." />; } }
注:為了幫助您從使用字串 ref 切換到回撥 ref
,您可以使用以下 codemod 命令:
npx codemod@latest react/19/replace-string-ref
5. 移除模組模式工廠
React 19 將移除的另一個廢棄功能是模組模式工廠。這種模式很少被使用,而且會導致 React 略微變大和變慢。
模組模式工廠允許開發人員不那麼傳統地建立元件。下面是一個您可能正在使用它的示例:
function SettingsPanelFactory() { return { render() { return ( <div className="settings-panel"> <h2>Settings</h2> {/* other settings UI components */} </div> ); } }; }
在此模式中,SettingsPanelFactory
使用 render
方法返回物件,而不是直接返回 JSX。
為了符合 React 19 的要求,您必須將模組模式工廠遷移到直接返回 JSX 的常規函式。以下是更新後的示例:
function SettingsPanel() { return ( <div className="settings-panel"> <h2>Settings</h2> {/* other settings UI components */} </div> ); }
6. 移除 createFactory API
React 19 將移除 React.createFactory
。在JSX得到廣泛支援之前,這種方法比較常用。它允許開發人員在不使用 JSX 語法的情況下建立 React 元素。
不過,隨著 JSX 的普及,createFactory
已經過時,可以用更簡單、更易讀的 JSX 程式碼來替代。
下面是一個使用 createFactory
建立 button
元素的示例。這可能是自定義 WordPress 外掛的一部分,該外掛可根據使用者輸入動態生成 button
元素:
import { createFactory } from 'react'; const button = createFactory('button'); function CustomButton() { return button({ className: 'custom-button', type: 'button' }, 'Click Me'); }
要為 React 19 更新此程式碼,請將 createFactory
替換為 JSX。這一改動使程式碼更現代、更易讀、更易維護:
function CustomButton() { return <button className="custom-button" type="button">Click Me</button>; }
7. 移除 react-test-renderer/shallow
React 19 刪除了 react-test-renderer/shallow
,以簡化測試實用程式並鼓勵最佳實踐。在 React 18 中,react-test-renderer/shallow
已更新為重新匯出 react-shallow-renderer。
以前,您可能會使用 react-test-renderer/shallow
為 React 元件建立淺層呈現測試:
import ShallowRenderer from 'react-test-renderer/shallow'; test('MyComponent shallow render', () => { const renderer = new ShallowRenderer(); renderer.render(<MyComponent />); const result = renderer.getRenderOutput(); expect(result.type).toBe('div'); });
要符合 React 19 的要求,需要安裝 react-shallow-renderer:
npm install react-shallow-renderer --save-dev
並更新您的匯入:
import ShallowRenderer from 'react-shallow-renderer'; test('MyComponent shallow render', () => { const renderer = new ShallowRenderer(); renderer.render(<MyComponent />); const result = renderer.getRenderOutput(); expect(result.type).toBe('div'); });
React 團隊建議遷移到 React 測試庫,該庫通過關注使用者如何與元件互動來提供更強大的測試實踐。
為此,請將 @testing-library/react 庫作為開發依賴安裝:
npm install @testing-library/react --save-dev
接下來,您可以使用這種現代方法測試同一個元件:
import { render, screen } from '@testing-library/react'; import MyBlock from './MyBlock'; test('MyBlock renders correctly', () => { render(<MyBlock />); const element = screen.getByText('MyBlock content'); expect(element).toBeInTheDocument(); });
刪除 React DOM 中的棄用方法
React DOM 在 React 19 中也發生了變化,刪除了某些已廢棄的方法。本節將概述這些更改,並指導您更新與 DOM 相關的程式碼。
1. 刪除 react-dom/test-utils API
react-dom/test-utils API 也將在 React 19 中移除。這將影響我們為 React 元件編寫測試的方式。具體來說,act
工具已從 react-dom/test-utils
移至 react
包。
此外,react-dom/test-utils
中的大多數其他實用工具也已移除。下面介紹如何調整測試以適應這些變化。
act
實用程式對於確保與測試相關的所有更新都已處理並應用到 DOM 至關重要。在 React 19 中,您應該直接從 react
中匯入 act
,而不是 react-dom/test-utils
。
// Before import { act } from 'react-dom/test-utils'; // Now import { act } from 'react';
注:為了幫助你從使用 react-dom/test-utils
切換到新的匯入,你可以使用下面的 codemod 命令:
npx codemod@latest react/19/replace-act-import
React 團隊還建議將您的測試遷移到 React 測試庫,以獲得現代化且支援良好的測試體驗。以下是一些常見用例以及如何更新它們。
renderIntoDocument
實用程式將被移除。您可以使用 @testing-library/react
中的 render
來替換它。
// Before import { renderIntoDocument } from 'react-dom/test-utils'; renderIntoDocument(<Component />); // Now import { render } from '@testing-library/react'; render(<Component />);
同樣,用於模擬事件的 Simulate
工具也將被移除。取而代之的是使用 @testing-library/react
中的 fireEvent
,它會在元素上派發實際事件。
// Before import { Simulate } from 'react-dom/test-utils'; const element = document.querySelector('button'); Simulate.click(element); // Now import { fireEvent } from '@testing-library/react'; const element = document.querySelector('button'); fireEvent.click(element);
請注意,fireEvent
派發的是真實事件,這意味著它與元素的互動比模擬
建立的合成事件更自然。要正確理解 React 測試庫,請閱讀其文件。
2. 刪除 findDOMNode API
React 19 的另一個重大變化是移除了 ReactDOM .findDOMNode
,該函式在 React 16.6.0 中已被棄用。
該函式用於訪問 React 元件的底層 DOM 節點,但它有幾個缺點,例如執行速度慢、易受重構影響和破壞抽象層。
相反,您應該使用 DOM refs,它提供了一種更可靠、更高效的方式來與 React 元件中的 DOM 元素進行互動。
下面是使用 findDOMNode
在元件掛載時選擇輸入欄位中文字的示例:
import { findDOMNode } from 'react-dom'; function AutoselectingInput() { useEffect(() => { const input = findDOMNode(this); input.select() }, []); render() { return <input defaultValue="Hello" />; } }
要為 React 19 更新此程式碼,請將 findDOMNode
替換為 ref
。這一改動使程式碼更加健壯,並與現代 React 實踐保持一致:
import React, { useEffect, useRef } from 'react'; function AutoselectingInput() { const inputRef = useRef(null); useEffect(() => { inputRef.current.select(); }, []); return <input ref={inputRef} defaultValue="Hello" />; }
3. 移除渲染 API
React 19 將移除 ReactDOM.
render。該方法已在 React 18.0.0 中被棄用,取而代之的是 react-dom/client
中的 createRoot
API,它為初始化和渲染 React 應用程式提供了一種更高效、更現代的方式。這一變化是 React 為簡化和優化庫而持續努力的一部分。
在典型的 WordPress 設定中,您可能會有一個自定義塊或外掛,在 DOM 準備就緒時初始化 React 應用程式。以前,您會使用 ReactDOM.render
:
import { render } from 'react-dom'; render(<App />, document.getElementById('root'));
在 React 19 中,您應該使用 createRoot
來初始化和呈現您的 React 應用程式:
import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')); root.render(<App />);
注:為了幫助您從使用 ReactDOM.render
切換到 react-dom/client
的 createRoot
API,您可以使用以下 codemod 命令:
npx codemod@latest react/19/replace-reactdom-render
4. 刪除 unmountComponentAtNode API
React 19 還移除了 ReactDOM.unmountComponentAtNode
方法,該方法在 React 18.0.0 中已被棄用。
在 React 19 中,您應該遷移到使用 root.unmount()
方法,該方法更符合用於建立和水化根的更新 API。
// Before unmountComponentAtNode(document.getElementById('root')); // Now root.unmount();
注:要從使用 unmountComponentAtNode
切換到 root.unmount
,可以使用以下 codemod 命令:
npx codemod@latest react/19/replace-reactdom-render
5. 移除 hydrate API
ReactDOM.hydrate 在 React18 中被棄用,並將在 React 19 中完全移除。
React DOM 客戶端 API 的新方法 hydrateRoot
將取代 ReactDOM.hydrate
,為伺服器渲染的 React 應用程式提供更高效、更現代的水合方式。
在 WordPress 環境中,您可能會使用伺服器端渲染(SSR)來交付初始 HTML 內容,以加快頁面載入速度。要將這些內容水合到互動式 React 應用程式中,您以前需要使用 ReactDOM.hydrate
:
import { hydrate } from 'react-dom'; import App from './App.js'; hydrate( <App />, document.getElementById('root') );
使用 React 19 時,應使用react-dom/client
中的hydrateRoot
進行 hydration:
import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot( document.getElementById('root'), <App /> );
注:To help you switch from ReactDOM.hydrate
to ReactDOMClient.hydrateRoot
, you can use the following codemod command:
npx codemod@latest react/19/replace-reactdom-render
刪除已廢棄的 TypeScript 型別
WordPress 開發人員經常使用 TypeScript 為 React 元件新增型別安全性並提高程式碼質量。在 React 19 中,一些已被棄用的 TypeScript 型別已被移除或遷移到更相關的包中。
瞭解這些變化對於確保您的程式碼庫保持穩健並與最新的 React 版本相容至關重要。
為了協助過渡,React 團隊提供了一個名為 types-react-codemod 的工具,它可以自動更新您的程式碼庫以處理這些變更。
要使用該工具,請執行下面的 codemod 命令,其中包含幾個用於更新已廢棄型別的轉換。
npx types-react-codemod@latest preset-19 ./path-to-app
該工具還提供互動模式,您可以選擇要應用的特定變換:
? Pick transforms to apply (Press to select, to toggle all, to invert selection, and to proceed) ❯◯ context-any ◉ deprecated-react-type ◉ deprecated-sfc-element ◉ deprecated-sfc ◉ deprecated-stateless-component ◯ implicit-children ◯ useCallback-implicit-any
讓我們舉例說明一些關鍵的變化。
1. 需要 ref 清理
在 React 19 中,ref
清理函式通過在 ref
回撥中強制執行顯式返回來提高型別安全性。隱式返回會導致 TypeScript 誤解返回值。
// Before (instance = current)} /> // Now { instance = current }} />
2. useRef 需要一個引數
以前,useRef
可以在沒有引數的情況下呼叫,從而導致潛在的型別問題。在 React 19 中,useRef
需要一個引數,以確保 ref 始終是可變的。
// Before — @ts-expect-error: Expected 1 argument but saw none useRef(); // Now — correct usage with an argument useRef(undefined);
3. 對 ReactElement TypeScript 型別的更改
ReactElement
props 的預設型別已從 any
變為 unknown
,通過要求顯式處理未知型別,提高了型別安全性。
// Previously, this was 'any' type Example = ReactElement["props"]; // Now, this is 'unknown' type Example = ReactElement["props"];
如果您的程式碼依賴於any
型別,則必須更新程式碼以顯式處理 unknown
型別或將其轉換為 any
型別。
小結
作為 WordPress 開發人員,瞭解 React 的最新進展至關重要。本指南將確保您瞭解 React 即將發生的各種變化,以便將它們應用到您的 WordPress 專案中。
最後一條資訊: React 19 將要求使用新的 JSX transform。好訊息是,WordPress 6.6 已經配備了它。如果未啟用新 transform,您將看到以下警告:
Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance: https://react.dev/link/new-jsx-transform
您所要做的就是停止使用 React 匯入進行 JSX 轉換,因為它們已不再必要。
評論留言