React 19 アップグレードガイド
2024年4月25日 by Ricky Hanlon
React 19に追加された改善には一部の破壊的変更が必要ですが、可能な限りスムーズなアップグレードを実現するよう努めており、ほとんどのアプリに影響を与えることはないと予想しています。
注意:React 18.3も公開されました
React 19へのアップグレードを容易にするため、18.2と同一でありながら、非推奨APIやReact 19に必要なその他の変更に対する警告を追加したreact@18.3リリースを公開しました。React 19にアップグレードする前に、まずReact 18.3にアップグレードして問題を特定することをお勧めします。
18.3の変更一覧については、リリースノートをご覧ください。
この投稿では、React 19へのアップグレード手順をガイドします:
- インストール
- Codemods
- 破壊的変更
- 新しい非推奨事項
- 注目すべき変更
- TypeScript の変更
- 変更履歴
React 19のテストにご協力いただける場合は、このアップグレードガイドの手順に従って、遭遇した問題を報告してください。React 19に追加された新機能の一覧については、React 19リリース投稿をご覧ください。
インストール
注意:新しいJSX Transformが必要になりました
2020年にバンドルサイズを改善し、ReactをインポートせずにJSXを使用するための新しいJSX transformを導入しました。React 19では、refをpropとして使用することやJSXの速度改善など、新しいtransformを必要とする追加の改善を加えています。
新しいtransformが有効になっていない場合、次の警告が表示されます:
Console
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
transformはほとんどの環境ですでに有効になっているため、ほとんどのアプリは影響を受けないと予想しています。アップグレード方法の手動手順については、アナウンス投稿をご覧ください。
ReactとReact DOMの最新バージョンをインストールするには:
npm install --save-exact react@^19.0.0 react-dom@^19.0.0
または、Yarnを使用している場合:
yarn add --exact react@^19.0.0 react-dom@^19.0.0
TypeScriptを使用している場合は、型定義も更新する必要があります:
npm install --save-exact @types/react@^19.0.0 @types/react-dom@^19.0.0
または、Yarnを使用している場合:
yarn add --exact @types/react@^19.0.0 @types/react-dom@^19.0.0
最も一般的な置換のためのcodemodも含めています。以下のTypeScriptの変更をご覧ください。
Codemods
アップグレードを支援するため、codemod.comのチームと協力して、React 19の多くの新しいAPIとパターンにコードを自動的に更新するcodemodを公開しました。
すべてのcodemodはreact-codemodリポジトリで利用可能で、Codemodチームがcodemodの保守に参加しています。
これらのcodemodを実行するには、react-codemodの代わりにcodemodコマンドを使用することをお勧めします。これはより高速に実行され、より複雑なコード移行を処理し、TypeScriptのより良いサポートを提供します。
注意:すべてのReact 19 codemodを実行
React 19 codemodレシピを使用して、このガイドに記載されているすべてのcodemodを実行します:
npx codemod@latest react/19/migration-recipe
これにより、react-codemodから以下のcodemodが実行されます:
- replace-reactdom-render
- replace-string-ref
- replace-act-import
- replace-use-form-state
- prop-types-typescript
これにはTypeScriptの変更は含まれません。以下のTypeScriptの変更をご覧ください。
codemodを含む変更には、以下にコマンドが含まれています。利用可能なすべてのcodemodの一覧については、react-codemodリポジトリをご覧ください。
破壊的変更
renderでのエラーが再スローされなくなりました
以前のバージョンのReactでは、render中にスローされたエラーはキャッチされて再スローされていました。DEVでは、console.errorにもログを出力し、重複したエラーログが発生していました。
React 19では、再スローしないことで重複を減らし、エラーの処理方法を改善しました:
- キャッチされないエラー:Error Boundaryでキャッチされないエラーは
window.reportErrorに報告されます
- キャッチされたエラー:Error Boundaryでキャッチされたエラーは
console.errorに報告されます
この変更はほとんどのアプリに影響しないはずですが、本番環境のエラー報告がエラーの再スローに依存している場合は、エラーハンドリングを更新する必要があるかもしれません。
これをサポートするため、カスタムエラーハンドリングのためにcreateRootとhydrateRootに新しいメソッドを追加しました:
const root = createRoot(container, {
onUncaughtError: (error, errorInfo) => {
},
onCaughtError: (error, errorInfo) => {
}
});
詳細については、createRootとhydrateRootのドキュメントをご覧ください。
削除された非推奨のReact API
削除:関数のpropTypesとdefaultProps
PropTypesは2017年4月(v15.5.0)に非推奨になりました。React 19では、ReactパッケージからpropTypeチェックを削除し、使用しても静かに無視されます。
propTypesを使用している場合は、TypeScriptまたは他の型チェックソリューションへの移行をお勧めします。
また、ES6のデフォルトパラメータの代わりに、関数コンポーネントからdefaultPropsも削除しています。クラスコンポーネントはES6の代替手段がないため、引き続きdefaultPropsをサポートします。
import PropTypes from 'prop-types';
function Heading({ text }) {
return <h1>{text}</h1>;
}
Heading.propTypes = {
text: PropTypes.string,
};
Heading.defaultProps = {
text: 'Hello, world!',
};
interface Props {
text?: string;
}
function Heading({ text = 'Hello, world!' }: Props) {
return <h1>{text}</h1>;
}
注意:Codemod propTypesをTypeScriptに変換:
npx codemod@latest react/prop-types-typescript
削除:contextTypesとgetChildContextを使用するLegacy Context
Legacy Contextは2018年10月(v16.6.0)に非推奨になりました。Legacy ContextはcontextTypesとgetChildContext APIを使用するクラスコンポーネントでのみ利用可能で、見逃しやすい微妙なバグのためcontextTypeに置き換えられました。
React 19では、Reactを少し小さく高速にするためにLegacy Contextを削除しています。
クラスコンポーネントでまだLegacy Contextを使用している場合は、新しいcontextType APIに移行する必要があります:
import PropTypes from 'prop-types';
class Parent extends React.Component {
static childContextTypes = {
foo: PropTypes.string.isRequired,
};
getChildContext() {
return { foo: 'bar' };
}
render() {
return <Child />;
}
}
class Child extends React.Component {
static contextTypes = {
foo: PropTypes.string.isRequired,
};
render() {
return <div>{this.context.foo}</div>;
}
}
const FooContext = React.createContext();
class Parent extends React.Component {
render() {
return (
<FooContext value='bar'>
<Child />
</FooContext>
);
}
}
class Child extends React.Component {
static contextType = FooContext;
render() {
return <div>{this.context}</div>;
}
}
削除:string refs
string refsは2018年3月(v16.3.0)に非推奨になりました。クラスコンポーネントは複数の欠点のためrefコールバックに置き換えられる前にstring refsをサポートしていました。
React 19では、Reactをよりシンプルで理解しやすくするためにstring refsを削除しています。
クラスコンポーネントでまだstring refsを使用している場合は、refコールバックに移行する必要があります:
class MyComponent extends React.Component {
componentDidMount() {
this.refs.input.focus();
}
render() {
return <input ref='input' />;
}
}
class MyComponent extends React.Component {
componentDidMount() {
this.input.focus();
}
render() {
return <input ref={input => this.input = input} />;
}
}
注意:Codemod string refsをrefコールバックに変換:
npx codemod@latest react/19/replace-string-ref
削除:Module pattern factories
Module pattern factoriesは2019年8月(v16.9.0)に非推奨になりました。このパターンはほとんど使用されておらず、サポートすることでReactが必要以上に少し大きく遅くなっていました。
React 19では、module pattern factoriesのサポートを削除し、通常の関数に移行する必要があります:
function FactoryComponent() {
return {
render() {
return <div />;
}
}
}
function FactoryComponent() {
return <div />;
}
削除:React.createFactory
createFactoryは2020年2月(v16.13.0)に非推奨になりました。JSXの幅広いサポート以前はcreateFactoryの使用が一般的でしたが、今日ではほとんど使用されておらず、JSXで置き換えることができます。
React 19では、createFactoryを削除し、JSXに移行する必要があります:
import { createFactory } from 'react';
const button = createFactory('button');
const button = <button />;
削除:react-test-renderer/shallow
React 18では、react-test-renderer/shallowをreact-shallow-rendererを再エクスポートするように更新しました。React 19では、パッケージを直接インストールすることを優先してreact-test-render/shallowを削除しています:
npm install react-shallow-renderer --save-dev
- import ShallowRenderer from 'react-test-renderer/shallow';
+ import ShallowRenderer from 'react-shallow-renderer';
注意:shallow renderingの再考をお願いします
Shallow renderingはReactの内部に依存しており、将来のアップグレードを阻害する可能性があります。テストを@testing-library/reactまたは@testing-library/react-nativeに移行することをお勧めします。
削除された非推奨のReact DOM API
削除:react-dom/test-utils
actをreact-dom/test-utilsからreactパッケージに移動しました:
Console
ReactDOMTestUtils.act is deprecated in favor of React.act. Import act from react instead of react-dom/test-utils. See https:
この警告を修正するには、reactからactをインポートできます:
- import { act } from 'react-dom/test-utils'
+ import { act } from 'react';
他のすべてのtest-utils関数は削除されました。これらのユーティリティは一般的ではなく、コンポーネントとReactの低レベル実装詳細に依存しすぎることを容易にしていました。React 19では、これらの関数は呼び出されるとエラーになり、そのエクスポートは将来のバージョンで削除されます。
代替案については警告ページをご覧ください。
注意:Codemod ReactDOMTestUtils.actをReact.actに変換:
npx codemod@latest react/19/replace-act-import
削除:ReactDOM.render
ReactDOM.renderは2022年3月(v18.0.0)に非推奨になりました。React 19では、ReactDOM.renderを削除し、ReactDOM.createRootの使用に移行する必要があります:
import { render } from 'react-dom';
render(<App />, document.getElementById('root'));
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
注意:Codemod ReactDOM.renderをReactDOMClient.createRootに変換:
npx codemod@latest react/19/replace-reactdom-render
削除:ReactDOM.hydrate
ReactDOM.hydrateは2022年3月(v18.0.0)に非推奨になりました。React 19では、ReactDOM.hydrateを削除し、ReactDOM.hydrateRootの使用に移行する必要があります:
import { hydrate } from 'react-dom';
hydrate(<App />, document.getElementById('root'));
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);
注意:Codemod ReactDOM.hydrateをReactDOMClient.hydrateRootに変換:
npx codemod@latest react/19/replace-reactdom-render
削除:unmountComponentAtNode
ReactDOM.unmountComponentAtNodeは2022年3月(v18.0.0)に非推奨になりました。React 19では、root.unmount()の使用に移行する必要があります:
unmountComponentAtNode(document.getElementById('root'));
root.unmount();
詳細については、createRootとhydrateRootのroot.unmount()をご覧ください。
注意:Codemod unmountComponentAtNodeをroot.unmountに変換:
npx codemod@latest react/19/replace-reactdom-render
削除:ReactDOM.findDOMNode
ReactDOM.findDOMNodeは2018年10月(v16.6.0)に非推奨になりました。findDOMNodeは実行が遅く、リファクタリングに脆弱で、最初の子のみを返し、抽象化レベルを破る従来のエスケープハッチだったため削除しています(詳細はこちら)。
ReactDOM.findDOMNodeをDOM refsで置き換えることができます: