WordPress開発では、独自のReactコンポーネントをテーマやプラグインに統合し、動的でレスポンシブなユーザーインターフェースを作成することがあります。
React 19のリリースが間近に迫る今、既存のコードベースに影響を与える可能性のある新機能や非推奨の変更に備えておくことが重要です。7月16日にリリース予定のWordPress 6.6には、React 18.3が導入されています。このバージョンは18.2とほぼ同じになりますが、React 19リリースに向けた非推奨の機能に対する警告が追加されています。
非推奨となる機能への対処は、React 19との互換性を確保するために不可欠です。対処を怠ると、React 19がリリースされWordPressに組み込まれた際に、カスタムブロックやプラグイン、テーマにバグや問題が発生する可能性があります。
そこで今回は、非推奨となる機能の概要とコード例、機能をシームレスに維持するために非推奨機能を置き換える方法をご紹介します。
Reactで削除される非推奨機能
Reactライブラリを効率化し、ベストプラクティスを促進する目的で、一部非推奨APIと機能が削除されました。以下主な変更点、およびコード更新方法を見ていきます。
1. 関数コンポーネントdefaultPropsの削除
React 19では、関数コンポーネントのdefaultProps
が削除され、ES6のデフォルトパラメータが採用されます。WordPressチームによると、この非推奨関数はプラグインやテーマで最も使用されています。
中には、defaultProps
を使って関数コンポーネントのpropsにデフォルト値を提供し、特定のpropsが渡されなくてもコンポーネントが正しく動作するようにしているWordPress開発者もいるかもしれません。
以下は、defaultProps
を使用した現在のコードの例です。
function CustomButton({ label, color }) {
return <button style={{ backgroundColor: color }}>{ label }</button>;
}
CustomButton.defaultProps = {
label: 'クリック',
color: 'blue',
};
CustomButton
コンポーネントは、defaultProps
によるデフォルトのlabel
とcolor
値を持っています。React 19では警告エラーが投げられ、ES6のデフォルトパラメータを代わりに使用するように促します。
ES6のデフォルトパラメータを使って更新すると、以下のようになります。
function CustomButton({ label = 'クリック', color = 'blue' }) {
return <button style={{ backgroundColor: color }}>{ label }</button>;
}
ES6のデフォルトパラメータを使用すると、デフォルト値が関数のシグネチャに直接記述されるためコードが読みやすくなり、メンテナンスも容易になります。
2. 関数コンポーネントpropTypesの削除
propTypes
はReact 15.5.0で非推奨となり、React 19で完全に削除される予定です。propTypes
を使用している場合は、TypeScriptまたは別の型チェックのソリューションに移行することが推奨されます。
propTypes
は、たとえば関数コンポーネントに渡されるpropが正しい型と値であることを確認するために使用されます。
import PropTypes from 'prop-types';
function CustomButton({ label, color }) {
return <button style={{ backgroundColor: color }}>{ label }</button>;
}
CustomButton.defaultProps = {
label: 'クリック',
color: 'blue',
};
CustomButton.propTypes = {
label: PropTypes.string,
color: PropTypes.string,
};
今後は、TypeScriptを使用して型チェックを行うことができます。
type CustomButtonProps = {
label?: string;
color?: string;
};
const CustomButton = ({ label = 'クリック', color = 'blue' }: CustomButtonProps) => {
return <button style={{ backgroundColor: color }}>{ label }</button>;
};
3. レガシーコンテキスト(contextTypesとgetChildContext)の削除
WordPressの多くのプラグインやコードベースで長年にわたって使用されてきたことから、クラスコンポーネントでcontextTypes
やgetChildContext
といった旧式のAPIを使用しているかもしれません。これらのAPIは、各レベルで明示的にpropsを渡すことなく、親コンポーネントからその子孫にデータを渡すために使用するのが一般的でした。
見落とされがちな細かなバグにより、このレガシーコンテキストはReact 16.6.0で非推奨となり、React 19で完全に削除されます。
今後は、contextType
APIを使用することになります。
WordPressプラグインで非推奨のContext APIを使用し、サイトタイトルなどのグローバル設定を親コンポーネントから子コンポーネントにprop drilling(バケツリレー)を回避して渡す例を見てみます。
import PropTypes from 'prop-types';
class SettingsProvider extends React.Component {
static childContextTypes = {
siteTitle: PropTypes.string.isRequired,
};
getChildContext() {
return { siteTitle: '私のWordPressサイト' };
}
render() {
return <SettingsConsumer />;
}
}
class SettingsConsumer extends React.Component {
static contextTypes = {
siteTitle: PropTypes.string.isRequired,
};
render() {
return <div>サイトタイトル: {this.context.siteTitle}</div>;
}
}
今後はReact 19への備えとして、createContext
メソッドを使用します。
import React from 'react';
const SettingsContext = React.createContext();
class SettingsProvider extends React.Component {
render() {
return (
<SettingsContext value={{ siteTitle: '私のWordPressサイト' }}>
<SettingsConsumer />
</SettingsContext>
);
}
}
class SettingsConsumer extends React.Component {
static contextType = SettingsContext;
render() {
const { siteTitle } = this.context;
return <div>サイトタイトル: { siteTitle }</div>;
}
}
4. 文字列形式refの削除
文字列形式の参照は、かつてReactコンポーネントでDOM要素にアクセスする一般的な方法でしたが、React 16.3.0で非推奨となり、React 19では削除される予定です。
文字列を使った参照は容易でしたが、名前が衝突する可能性や柔軟性の欠如など、いくつかの問題がありました。
WordPressのカスタムブロックで文字列を使った参照を行うとします。入力フィールドを含むGutenbergのカスタムブロックがあり、エディターにブロックが追加された際に入力フィールドが自動的に目立つようにしたい場合は、以下のようになります。
class CustomBlock extends React.Component {
componentDidMount() {
this.refs.input.focus();
}
render() {
return <input ref="input" placeholder="テキストを入力してください" />;
}
}
React 19に備えるにはコールバック形式のrefs
、またはReact.createRef
APIに置き換えます。コールバック形式のref
を使用すると以下のようになります。
class CustomBlock extends React.Component {
componentDidMount() {
this.input.focus();
}
render() {
return <input ref={(input) => (this.input = input)} placeholder="テキストを入力してください" />;
}
}
5. モジュールパターンファクトリの削除
React 19で削除されるもう1つの非推奨機能は、モジュールパターンファクトリです。これは現在ほとんど使用されておらず、Reactが必要以上に重くなり、遅くなる原因となっていました。
モジュールパターンファクトリの使用には、慣習的でないコンポーネントを作成できるというメリットがありました。
function SettingsPanelFactory() {
return {
render() {
return (
<div className="settings-panel">
<h2>設定</h2>
{/* その他の設定 UIコンポーネント */}
</div>
);
}
};
}
このパターンでは、SettingsPanelFactory
はJSXを直接返すのではなく、render
メソッドを使ってオブジェクトを返します。
React 19に対応するには、このモジュールパターンファクトリを、JSXを直接返す通常の関数に移行する必要があります。
function SettingsPanel() {
return (
<div className="settings-panel">
<h2> 設定</h2>
{/* その他の設定 UIコンポーネント */}
</div>
);
}
6. createFactory APIの削除
React 19では、React.createFactory
も削除されます。このメソッドは、JSXが広くサポートされる前までよく使用されており、JSX構文を使わずにReact要素を作成することができました。
JSXの普及に伴い、createFactory
は徐々に旧式のメソッドとなり、よりシンプルで読みやすいJSXコードに置き換えることができるようになりました。
以下は、createFactory
を使用してbutton
要素を作成する例です。button
要素をユーザーの入力に基づいて動的に生成するWordPressプラグインの開発などで見られます。
import { createFactory } from 'react';
const button = createFactory('button');
function CustomButton() {
return button({ className: 'custom-button', type: 'button' }, 'クリック');
}
このコードをReact 19に対応させるにはcreateFactory
をJSXに置き換えます。これによりコードが洗練され読みやすくなり、保守管理も簡単になります。
function CustomButton() {
return <button className="custom-button" type="button">クリック</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コンポーネントのshallow(浅い)レンダリングのテストを作成することができました。
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への移行を推奨しています。このライブラリにより、ユーザーがコンポーネントとどのようにやり取りするかに焦点を当てることで、より堅牢なテストプラクティスが実現します。
これを行うには、@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 19ではReact DOMが変更され、一部の非推奨メソッドも削除されます。ここからは削除される非推奨メソッドの概要と、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-dom/test-utils
ではなくreact
からact
を直接インポートします。
// これまで
import { act } from 'react-dom/test-utils';
// これから
import { act } from 'react';
Reactチームはまた、最新かつ十分にサポートされたテスト体験を考慮し、React Testing Libraryへの移行を推奨しています。以下、一般的な使用例とその更新方法をご紹介します。
renderIntoDocument
ユーティリティは削除され、@testing-library/react
からrender
に置き換えられます。
// これまで
import { renderIntoDocument } from 'react-dom/test-utils';
renderIntoDocument(<Component />);
// これから
import { render } from '@testing-library/react';
render(<Component />);
同様に、イベントを再現するためのSimulate
ユーティリティも削除されます。これには、要素に実際のイベントを発生させる@testing-library/react
のfireEvent
を使用します。
// これまで
import { Simulate } from 'react-dom/test-utils';
const element = document.querySelector('button');
Simulate.click(element);
// これから
import { fireEvent } from '@testing-library/react';
const element = document.querySelector('button');
fireEvent.click(element);
なお、fireEvent
は実際のイベントを発生させるため、Simulate
によって作成された合成イベントよりも自然に要素と相互作用します。React Testing Libraryの詳細はこちらをご覧ください。
2. findDOMNode APIの削除
React 16.6.0で非推奨となったReactDOM.findDOMNode
の削除もまた、React 19の重要な変更点です。
この関数は、Reactコンポーネントの基礎となるDOMノードにアクセスするために使用されていましたが、実行速度が遅い、リファクタリングが困難、抽象化レイヤーを破壊するなど、いくつかの欠点がありました。
今後は、ReactコンポーネントのDOM要素との対話により信頼性が高く効率的な方法を提供するDOM用のrefsを使用します。
以下は、コンポーネントがマウントされた際に入力フィールドのテキストを選択するために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. ReactDOM.renderの削除
ReactDOM.render
も削除されます。このメソッドはReact 18.0.0で非推奨となり、Reactアプリの初期化・レンダリングにより効率的で新しい方法を提供するreact-dom/client
からのcreateRoot
APIが代わりに採用されました。この変更は、ライブラリの合理化と最適化を目指すReactの継続的な取り組みの一環です。
一般的なWordPressの設定では、DOMの用意ができた際にReactアプリを初期化するカスタムブロックやプラグインがあります。以前は、このような状況でReactDOM.render
が使われていました。
import { render } from 'react-dom';
render(<App />, document.getElementById('root'));
React 19では、Reactアプリケーションの初期化とレンダリングにcreateRoot
を使用します。
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
4. unmountComponentAtNode APIの削除
React 18.0.0で非推奨となったReactDOM.unmountComponentAtNode
も削除されます。このメソッドは、ReactコンポーネントをDOMからアンマウントするために使用されていました。
React 19 では、ルーツの作成とハイドレーションのAPIの更新により、代わりにroot.unmount()
メソッドを使用します。
// これまで
unmountComponentAtNode(document.getElementById('root'));
// これから
root.unmount();
5. ReactDOM.hydrateの削除
ReactDOM.hydrateはReact 18で非推奨となり、React 19で完全に削除される予定です。
ReactDOM.hydrate
を置き換えるのは、クライアント用のReact DOM APIの新たなメソッドであるhydrateRoot
です。サーバーでレンダリングされた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
を使用します。
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(
document.getElementById('root'),
<App />
);
削除される非推奨のTypeScript型
WordPress開発では、Reactコンポーネントの型安全性、コードの質を向上させるためにTypeScriptを一般的に使用します。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が戻り値を誤解釈する原因になり得ます。
// これまで
(instance = current)} />
// これから
{ instance = current }} />
2. useRefの引数の必須化
以前は、引数なしでuseRef
を呼び出すことができたため、潜在的な型の問題を引き起こしていました。React 19では、useRef
はrefが常にミュータブルであることを保証するために引数を必要とします。
// これまで — @ts-expect-error: 1つの引数が期待されていたが何も見つからなかった
useRef();
// これから — 引数を使った正しい使用方法
useRef(undefined);
3. ReactElement TypeScript型の変更
ReactElement
propsのデフォルトの型がany
からunknown
に変更され、未知の型の明示的な処理を要求することで、型の安全性が向上します。
// これまで ─ 'any'
type Example = ReactElement["props"];
// これから ─ 'unknown'
type Example = ReactElement["props"];
any
に依存していたコードは、unknown
を明示的に処理するように更新するか、any
にキャストする必要があります。
まとめ
WordPress開発を行う場合、最新のReactに対応することは非常に重要です。今回は、Reactのさまざまな変更点をご紹介し、WordPressプロジェクトに適用する方法をご紹介しました。
React 19では、新たなJSXトランスフォームが必要になりますが、幸いWordPress 6.6に標準搭載されます。このトランスフォームが有効になっていない場合は、以下のような警告が表示されます。
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
アプリケーション(またはその依存関係の1つ)が古いJSXトランスフォームを使用しています。最新のものに更新してパフォーマンスを向上させてください
なお、JSXトランスフォームにReactインポートを使用する必要はありません。
React 19への対応に関して紹介が漏れている点やご質問などがありましたら、以下のコメント欄でお知らせください。
コメントを残す