` のように渡すことで、React に DOM ノードを `myRef.current` に入れるよう指示する。
- 通常、フォーカス、スクロール、または DOM 要素の測定などの非破壊的なアクションに ref を使用する。
-- コンポーネントはデフォルトでは内部の DOM ノードを公開しない。`forwardRef` を使用して特定のノードに 2 番目の `ref` 引数を渡すことで、DOM ノードの公開を明示的に許可する。
+- コンポーネントはデフォルトでは内部の DOM ノードを公開しない。props として `ref` を用いることで、DOM ノードの公開を明示的に許可する。
- React によって管理される DOM ノードの変更を避ける。
- React によって管理される DOM ノードをどうしても変更する場合は、React が更新する理由のない部分のみ変更する。
@@ -1049,7 +1049,7 @@ img {
-`SearchInput` のような独自コンポーネントから DOM ノードを公開するためには、`forwardRef` が必要です。
+`SearchInput` のような独自コンポーネントから DOM ノードを公開するためには、props としての `ref` の受け渡しが必要です。
@@ -1134,18 +1134,14 @@ export default function SearchButton({ onClick }) {
```
```js src/SearchInput.js
-import { forwardRef } from 'react';
-
-export default forwardRef(
- function SearchInput(props, ref) {
- return (
-
- );
- }
-);
+export default function SearchInput({ ref }) {
+ return (
+
+ );
+}
```
```css
diff --git a/src/content/learn/passing-data-deeply-with-context.md b/src/content/learn/passing-data-deeply-with-context.md
index d045771af..e1ddd8bad 100644
--- a/src/content/learn/passing-data-deeply-with-context.md
+++ b/src/content/learn/passing-data-deeply-with-context.md
@@ -468,15 +468,15 @@ import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
);
}
```
-これにより、「この `
` の下にあるコンポーネントが `LevelContext` の値を要求した場合、この `level` を渡せ」と React に伝えていることになります。コンポーネントは、UI ツリー内の上側で、最も近い `` の値を使用します。
+これにより、「この `` の下にあるコンポーネントが `LevelContext` の値を要求した場合、この `level` を渡せ」と React に伝えていることになります。コンポーネントは、UI ツリー内の上側で、最も近い `` の値を使用します。
@@ -514,9 +514,9 @@ import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
);
}
@@ -567,7 +567,7 @@ export const LevelContext = createContext(1);
元のコードと見た目の結果は同じですが、`level` を props として個々の `Heading` コンポーネントに渡さずに済んでいます! 代わりに、見出しは最も近い `Section` に値を要求して、自分の見出しレベルを自分で「判断」しているのです。
1. `` に props として `level` を渡す。
-2. `Section` は子要素を `` でラップする。
+2. `Section` は子要素を `` でラップする。
3. `Heading` は `useContext(LevelContext)` とすることで、上にある最も近い `LevelContext` の値を要求する。
## 同一コンポーネントでコンテクストを使用しつつ提供 {/*using-and-providing-context-from-the-same-component*/}
@@ -595,9 +595,9 @@ export default function Section({ children }) {
const level = useContext(LevelContext);
return (
);
}
@@ -643,9 +643,9 @@ export default function Section({ children }) {
const level = useContext(LevelContext);
return (
);
}
@@ -776,9 +776,9 @@ export default function Section({ children, isFancy }) {
'section ' +
(isFancy ? 'fancy' : '')
}>
-
+
{children}
-
+
);
}
@@ -868,7 +868,7 @@ CSS では、`color` や `background-color` といった異なるプロパティ
* コンテクストを使うには:
1. `export const MyContext = createContext(defaultValue)` を使用して作成およびエクスポートする。
2. フックに `useContext(MyContext)` のようにコンテクストを渡せば、どんな深い子コンポーネントからも値が読み取れる。
- 3. コンテクストの値を提供するには子要素を `
` でラップする。
+ 3. コンテクストの値を提供するには子要素を `` でラップする。
* コンテクストは中間コンポーネントを貫通する。
* コンテクストを使えば、「周囲に適応する」コンポーネントが書ける。
* コンテクストを使用する前に、props を渡すか、`children` として JSX を渡す方法を検討してみる。
@@ -1022,7 +1022,7 @@ li {
すべてのコンポーネントの props から `imageSize` を削除します。
-`Context.js` で `ImageSizeContext` を作成してエクスポートします。次に、List を `` でラップすることで下に値を渡します。`PlaceImage` で `useContext(ImageSizeContext)` を使ってそれを読み取ります。
+`Context.js` で `ImageSizeContext` を作成してエクスポートします。次に、List を `` でラップすることで下に値を渡します。`PlaceImage` で `useContext(ImageSizeContext)` を使ってそれを読み取ります。
@@ -1036,7 +1036,7 @@ export default function App() {
const [isLarge, setIsLarge] = useState(false);
const imageSize = isLarge ? 150 : 100;
return (
-
-
+
)
}
diff --git a/src/content/learn/react-compiler.md b/src/content/learn/react-compiler.md
index d2b979b4d..36c02eeb9 100644
--- a/src/content/learn/react-compiler.md
+++ b/src/content/learn/react-compiler.md
@@ -311,7 +311,7 @@ export default defineConfig({
### Webpack {/*usage-with-webpack*/}
-コミュニティによる Webpack ローダは[こちらで利用可能](https://github.com/SukkaW/react-compiler-webpack)です。
+コミュニティによる webpack ローダは[こちらで利用可能](https://github.com/SukkaW/react-compiler-webpack)です。
### Expo {/*usage-with-expo*/}
diff --git a/src/content/learn/react-developer-tools.md b/src/content/learn/react-developer-tools.md
index 5694d46f9..ef3b1a576 100644
--- a/src/content/learn/react-developer-tools.md
+++ b/src/content/learn/react-developer-tools.md
@@ -54,7 +54,7 @@ react-devtools
## モバイル (React Native) {/*mobile-react-native*/}
-[React Native](https://reactnative.dev/) で作成するアプリの調査を行う場合は、React Developer Tools と密に統合された組み込みデバッガである [React Native DevTools](https://reactnative.dev/docs/debugging/react-native-devtools) を使用できます。要素のハイライトや選択を含むすべての機能が、ブラウザ版の機能拡張と同様に動作します。
+[React Native](https://reactnative.dev/) で作成するアプリの調査を行う場合は、React Developer Tools と密に統合された組み込みデバッガである [React Native DevTools](https://reactnative.dev/docs/react-native-devtools) を使用できます。要素のハイライトや選択を含むすべての機能が、ブラウザ版の機能拡張と同様に動作します。
[React Native のデバッグについてさらに読む](https://reactnative.dev/docs/debugging)
diff --git a/src/content/learn/setup.md b/src/content/learn/setup.md
new file mode 100644
index 000000000..70e91dd8a
--- /dev/null
+++ b/src/content/learn/setup.md
@@ -0,0 +1,28 @@
+---
+title: セットアップ
+---
+
+
+React はエディタ、TypeScript、ブラウザ拡張機能、コンパイラといったツールと連携します。このセクションでは環境セットアップの方法を説明します。
+
+
+
+## エディタのセットアップ {/*editor-setup*/}
+
+[推奨エディタ](/learn/editor-setup)を確認し、React での作業に適したセットアップ方法を学びましょう。
+
+## TypeScript の使用 {/*using-typescript*/}
+
+TypeScript は JavaScript のコードベースに型定義を追加する一般的な方法です。[React プロジェクトに TypeScript を組み込む方法を学びましょう](/learn/typescript)。
+
+## React Developer Tools {/*react-developer-tools*/}
+
+React Developer Tools は React コンポーネントの調査を行い、props や state を編集し、パフォーマンスの問題を特定できるブラウザ拡張機能です。インストール方法は[こちら](learn/react-developer-tools)で確認できます。
+
+## React Compiler {/*react-compiler*/}
+
+React Compiler は React アプリを自動的に最適化するツールです。[詳細はこちら](/learn/react-compiler)。
+
+## 次のステップ {/*next-steps*/}
+
+[クイックスタート](/learn)ガイドに進んで、日常的に遭遇する最も重要な React の概念についてのツアーを始めましょう。
\ No newline at end of file
diff --git a/src/content/learn/start-a-new-react-project.md b/src/content/learn/start-a-new-react-project.md
deleted file mode 100644
index c35416975..000000000
--- a/src/content/learn/start-a-new-react-project.md
+++ /dev/null
@@ -1,130 +0,0 @@
----
-title: React プロジェクトを始める
----
-
-
-
-React だけで新しいアプリやウェブサイトを作りたい場合は、コミュニティで人気のある React フレームワークから、ひとつを選ぶことをおすすめします。
-
-
-
-
-フレームワークなしで React を使うことも可能ですが、ほとんどのアプリやサイトにおいては、コード分割、ルーティング、データ取得、HTML 生成といった問題に対処するための開発が必要であることが分かっています。これらは React に限らずあらゆる UI ライブラリに共通の問題です。
-
-フレームワークを使ってスタートすることで React での開発を素早く立ち上げ、後で実質的に独自フレームワークのようなものを作ってしまわずに済むようになるでしょう。
-
-
-
-#### フレームワークなしで React を使うことは可能? {/*can-i-use-react-without-a-framework*/}
-
-React をフレームワークなしで使うことも確かに可能です。[既存のページに React を追加する](/learn/add-react-to-an-existing-project#using-react-for-a-part-of-your-existing-page)場合はそのようにします。**しかし、新しいアプリやサイトをフルで React を使って構築する場合は、フレームワークを使用することをお勧めします。**
-
-理由は次のとおりです。
-
-もし最初にルーティングやデータ取得が必要ない場合でも、後になってそれらのためにライブラリを追加する必要が出てくる可能性が高いでしょう。新しい機能が増えるたびに JavaScript バンドルは大きくなっていき、個々のルートごとにコードを分割する方法を考える必要があります。データ取得の要件が複雑になるにつれて、サーバ・クライアント間のネットワークウォーターフォールが原因となり、アプリは非常に遅く感じるようになるでしょう。低速なネットワーク環境やロースペックなデバイスのユーザが増えると、コンテンツをできるだけ早く表示するため、サーバ上であるいはビルド時に、コンポーネントから HTML を生成する必要が生じることがあるでしょう。後になってセットアップを変更し、サーバ上であるいはビルド時にあなたのコードの一部が実行されるようにすることは、非常に複雑な作業です。
-
-**これらの問題は React に固有のものではありません。まさにこれが、Svelte には SvelteKit、Vue には Nuxt といったフレームワークが存在する理由です**。これらの問題を自力で解決するには、ルータやデータ取得ライブラリをバンドラに結合する作業を自分で行う必要があります。最初のセットアップをひとまず動作させることは難しくありませんが、時間が経ってアプリが成長してもなお素早く読み込めるサイトを作るためには、数々の細々とした問題に対処する必要が出てきます。アプリに必要な最小限のコードを 1 回のクライアント・サーバ間の往復で送信しつつ、並行してページ表示に必要なデータも送信したい、と思い始めるでしょう。ページが段階的に読み込まれ、JavaScript コードが実行すらされないうちから操作可能になるプログレッシブ・エンハンスメントのサポートが欲しくなるでしょう。どこにでもホストでき JavaScript が無効になっていても動作する、マーケティングページのための完全に静的な HTML ファイルが入ったフォルダを生成したい、と考え始めるでしょう。これらの機能を自分で構築するには、大変な労力が必要です。
-
-**このページで紹介する React フレームワークは、これらの問題をデフォルトで解決しているため、あなたが余計な作業をする必要はありません**。これらのフレームワークを使用することで、非常にスリムに始めて、ニーズに応じてアプリをスケーリングできます。各 React フレームワークにはコミュニティがあるため、質問に対する回答を見つけたり、ツールのアップグレードをしたりすることもより簡単に行えます。フレームワークはあなたのコードに構造を与えるので、あなたや他の人が複数のプロジェクト間でコンテクストやスキルを保持するのにも役立ちます。逆に、カスタムセットアップを行った場合、サポートされなくなった依存関係バージョンにハマる可能性が高まり、いずれ実質的には独自フレームワークのようなものを作成する羽目に陥ります。ただしそのようなフレームワークにはコミュニティもアップグレードパスもなく、仮に過去に作成されていたものに近かったとしても、行き当たりばったりで設計されたものに過ぎないわけですが。
-
-以下のフレームワークではうまく対処できない特殊な制約がある場合や、これらの問題に自分自身で対処したいという場合は、React で自分独自のカスタムセットアップを行うことも可能です。npm から `react` と `react-dom` を入手し、[Vite](https://vitejs.dev/) や [Parcel](https://parceljs.org/) のようなバンドラを使ってカスタムビルドプロセスをセットアップし、ルーティング、静的ファイル生成、サーバーサイドレンダリングなどのための各種ツールを必要に応じて追加していってください。
-
-
-
-## 本番環境対応の React フレームワーク {/*production-grade-react-frameworks*/}
-
-以下に挙げるフレームワークは、アプリを本番環境でデプロイしスケールさせるために必要なすべての機能を備えており、我々の[フルスタックアーキテクチャ](#which-features-make-up-the-react-teams-full-stack-architecture-vision)の実現に向けて開発されています。ここでお勧めするフレームワークはすべてオープンソースであり、助けになる活発なコミュニティがあり、自分自身のサーバにもホスティングプロバイダにもデプロイできます。このリストに掲載を希望するフレームワークの作者は[お知らせください](https://github.com/reactjs/react.dev/issues/new?assignees=&labels=type%3A+framework&projects=&template=3-framework.yml&title=%5BFramework%5D%3A+)。
-
-### Next.js {/*nextjs-pages-router*/}
-
-**[Next.js の Pages Router](https://nextjs.org/) はフルスタックの React フレームワークです**。ほぼ静的なブログサイトから複雑でダイナミックなアプリまで、どんな規模の React アプリでも作成できる万能フレームワークです。Next.js プロジェクトを新規に作るには、ターミナルで次のコマンドを実行してください。
-
-
-npx create-next-app@latest
-
-
-Next.js を初めて使う場合は、[Next.js の学習コース](https://nextjs.org/learn)を参照してください。
-
-Next.js は [Vercel](https://vercel.com/) によってメンテナンスされています。Next.js アプリは Node.js やサーバレスホスティングサービス、または自分自身のサーバーに[デプロイする](https://nextjs.org/docs/app/building-your-application/deploying)ことができます。Next.js はサーバを必要としない[静的なエクスポート](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports)もサポートしています。
-
-### Remix {/*remix*/}
-
-**[Remix](https://remix.run/) は、ネスト状のルーティングを備えたフルスタック React フレームワークです**。複雑なアプリを階層的に分割し、並列に読み込み、ユーザアクションに応じてリフレッシュすることができます。Remix プロジェクトを新規に作成するには、次のコマンドを実行します。
-
-
-npx create-remix
-
-
-Remix を初めて使う場合は、Remix の[ブログ作成チュートリアル](https://remix.run/docs/en/main/tutorials/blog)(短い)や [アプリ作成チュートリアル](https://remix.run/docs/en/main/tutorials/jokes)(長い)を参照してください。
-
-Remix は [Shopify](https://www.shopify.com/) によってメンテナンスされています。Remix アプリをデプロイするには、デプロイ先を[選択する必要があります](https://remix.run/docs/en/main/guides/deployment)。Remix アプリは、[アダプタ](https://remix.run/docs/en/main/other-api/adapter)を使用するか自分で書くことで、あらゆる Node.js またはサーバーレスホスティングにデプロイできます。
-
-### Gatsby {/*gatsby*/}
-
-**[Gatsby](https://www.gatsbyjs.com/) は、CMS ベースで高速なサイトを作成するための React フレームワークです**。豊富なプラグインのエコシステムと GraphQL データレイヤーにより、コンテンツ、API、サービスの統合が簡素化されます。Gatsby プロジェクトを新規に作成するには、次のコマンドを実行します。
-
-
-npx create-gatsby
-
-
-Gatsby を初めて使う場合は、[Gatsby チュートリアル](https://www.gatsbyjs.com/docs/tutorial/)を参照してください。
-
-Gatsby は [Netlify](https://www.netlify.com/) によってメンテナンスされています。[完全に静的な Gatsby サイト](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting) は、どんな静的なホスティングにもデプロイ可能です。サーバーサイド専用の機能を使用する場合は、ホスティングプロバイダが Gatsby に対応しているかどうか確認してください。
-
-### Expo(ネイティブアプリ向け) {/*expo*/}
-
-**[Expo](https://expo.dev/) は、Android、iOS、およびウェブ向けに、真にネイティブな UI を持ったユニバーサルアプリを作成できる React フレームワークです**。[React Native](https://reactnative.dev/) 用の SDK を提供し、ネイティブなパーツの使用を簡素化します。Expo プロジェクトを新規に作成するには、次のコマンドを実行します。
-
-
-npx create-expo-app
-
-
-Expo を初めて使う場合は、[Expo チュートリアル](https://docs.expo.dev/tutorial/introduction/)を参照してください。
-
-Expo は [Expo(社名)](https://expo.dev/about) によってメンテナンスされています。Expo を使用してアプリをビルドすることは無料であり、Google や Apple のアプリストアに制限なくアップロードすることができます。また Expo では有料のクラウドサービスも提供しています。
-
-## 超最先端の React フレームワーク {/*bleeding-edge-react-frameworks*/}
-
-我々が React の進化について探求する中で、React をフレームワークと(特にルーティング、バンドル作成、サーバテクノロジーと)より密接に統合することが、React ユーザがよりよいアプリを構築する手助けをするための最大の機会となるということに気づきました。Next.js チームは、[React Server Components](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components) のようなフレームワークに依存しない最先端の React 機能に関して、私たちと共同で研究、開発、統合、テストを行うことに同意しました。
-
-これらの機能は、本番環境で使える段階へと日々近づいており、他のバンドラやフレームワーク開発者とも統合について話し合っています。私たちの希望は、このページにリストされているすべてのフレームワークが、1 年か 2 年のうちにこれらの機能を完全にサポートするようになることです。(あなたがフレームワーク作者で、これらの機能を実験するため我々と協力することに興味がある場合、ぜひご連絡ください!)
-
-### Next.js (App Router) {/*nextjs-app-router*/}
-
-**[Next.js の App Router](https://nextjs.org/docs) は、React チームのフルスタックアーキテクチャビジョンを実現するために再設計された Next.js の API です**。サーバ上で、あるいはビルド時に非同期コンポーネントからデータのフェッチが行えるようになります。
-
-Next.js は [Vercel](https://vercel.com/) によってメンテナンスされています。[Next.js アプリのデプロイ](https://nextjs.org/docs/app/building-your-application/deploying)はあらゆる Next.js やサーバレスホスティングサービス上で行えます。Next.js は、サーバ不要の[静的エクスポート](https://nextjs.org/docs/app/building-your-application/deploying/static-exports)もサポートしています。
-
-
-
-#### React チームのフルスタックアーキテクチャビジョンに含まれる機能 {/*which-features-make-up-the-react-teams-full-stack-architecture-vision*/}
-
-Next.js の App Router バンドラは、公式の [React Server Components 仕様](https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md)を完全に実装しています。これにより単一の React ツリー内で、バンドル時専用コンポーネント、サーバ専用コンポーネント、インタラクティブなコンポーネントを混在させることができます。
-
-例えば、データベースやファイルから読み込みを行う React コンポーネントを非同期 (`async`) 関数として記述できます。そしてそのデータをインタラクティブなコンポーネントに渡すこともできます:
-
-```js
-// This component runs *only* on the server (or during the build).
-async function Talks({ confId }) {
- // 1. You're on the server, so you can talk to your data layer. API endpoint not required.
- const talks = await db.Talks.findAll({ confId });
-
- // 2. Add any amount of rendering logic. It won't make your JavaScript bundle larger.
- const videos = talks.map(talk => talk.video);
-
- // 3. Pass the data down to the components that will run in the browser.
- return ;
-}
-```
-
-Next.js の App Router は、[サスペンス (suspense) を使用したデータフェッチ](/blog/2022/03/29/react-v18#suspense-in-data-frameworks)を統合しています。これにより、React ツリー内で直接、UI の様々な場所に表示されるロード中状態(スケルトンプレースホルダなど)を指定できるようになります:
-
-```js
-}>
-
-
-```
-
-サーバコンポーネントとサスペンスは、Next.js の機能ではなく React の機能です。しかしフレームワークレベルでこれらを採用するには、合意形成とかなりの実装の手間が必要です。現時点では、Next.js の App Router が最も完全な実装です。React チームはバンドラの開発者と協力して、次世代のフレームワークでこれらの機能を実装しやすくすることを目指しています。
-
-
diff --git a/src/content/learn/state-a-components-memory.md b/src/content/learn/state-a-components-memory.md
index 04e744704..3478ff014 100644
--- a/src/content/learn/state-a-components-memory.md
+++ b/src/content/learn/state-a-components-memory.md
@@ -1452,7 +1452,7 @@ export default function FeedbackForm() {
#### 不要な state を削除 {/*remove-unnecessary-state*/}
-この例では、ボタンがクリックされると、ユーザの名前を尋ねて、挨拶を表示するアラートが表示されるはずです。名前を保持するために state を使用しようとしましたが、何らかの理由で常に "Hello, !" と表示されます。
+この例では、ボタンがクリックされると、ユーザの名前を尋ねて、挨拶を表示するアラートが表示されるはずです。名前を保持するために state を使用しようとしましたが、なぜか最初は "Hello, !" と表示され、その後も "Hello, [name]!" という形で、ひとつ前の入力値が表示されてしまいます。
このコードを修正するには、不要な state 変数を削除してください([この問題が発生した理由](/learn/state-as-a-snapshot)については後で説明します)。
diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md
index e6f2c0774..e0c9c233c 100644
--- a/src/content/reference/react-dom/client/createRoot.md
+++ b/src/content/reference/react-dom/client/createRoot.md
@@ -144,7 +144,7 @@ root.render();
-```html index.html
+```html public/index.html
My app
@@ -344,775 +344,127 @@ export default function App({counter}) {
`render` を複数回呼び出すことは滅多にありません。通常、コンポーネントは代わりに [state の更新](/reference/react/useState)を行います。
-### キャッチされないエラーに対するダイアログを表示 {/*show-a-dialog-for-uncaught-errors*/}
-
-デフォルトでは React は、キャッチされなかったエラーをコンソールにログとして表示します。独自のエラーレポーティングを実装するには、省略可能なルートオプションである `onUncaughtError` を指定します。
-
-```js [[1, 6, "onUncaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack"]]
-import { createRoot } from 'react-dom/client';
+### 本番環境でのエラーのロギング {/*error-logging-in-production*/}
-const root = createRoot(
- document.getElementById('root'),
- {
- onUncaughtError: (error, errorInfo) => {
- console.error(
- 'Uncaught error',
- error,
- errorInfo.componentStack
- );
- }
- }
-);
-root.render();
-```
-
-onUncaughtError オプションに指定するのは、以下の 2 つの引数を付けて呼ばれる関数です。
-
-1. スローされた error。
-2. errorInfo オブジェクト。エラーの componentStack を含んでいる。
+デフォルトでは、React はすべてのエラーをコンソールに記録します。独自のエラーレポートの仕組みを実装するには、省略可能なルートオプションとして `onUncaughtError`、`onCaughtError`、`onRecoverableError` のエラーハンドラを提供することができます。
-エラーダイアログを表示するために `onUncaughtError` ルートオプションを用いることが可能です。
-
-
-
-```html index.html hidden
-
-
-
- My app
-
-
-
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-
-
-
-```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
-}
-```
-
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
- }
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
- }
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
-}
-
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
-}
-
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
-}
-
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
-}
-```
-
-```js src/index.js active
+```js [[1, 6, "onCaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack", 15]]
import { createRoot } from "react-dom/client";
-import App from "./App.js";
-import {reportUncaughtError} from "./reportError";
-import "./styles.css";
+import { reportCaughtError } from "./reportError";
const container = document.getElementById("root");
const root = createRoot(container, {
- onUncaughtError: (error, errorInfo) => {
- if (error.message !== 'Known error') {
- reportUncaughtError({
+ onCaughtError: (error, errorInfo) => {
+ if (error.message !== "Known error") {
+ reportCaughtError({
error,
- componentStack: errorInfo.componentStack
+ componentStack: errorInfo.componentStack,
});
}
- }
+ },
});
-root.render();
-```
-
-```js src/App.js
-import { useState } from 'react';
-
-export default function App() {
- const [throwError, setThrowError] = useState(false);
-
- if (throwError) {
- foo.bar = 'baz';
- }
-
- return (
-
- This error shows the error dialog:
-
-
- );
-}
-```
-
-
-
-
-### エラーバウンダリでキャッチしたエラーを表示 {/*displaying-error-boundary-errors*/}
-
-デフォルトでは、React はエラーバウンダリによってキャッチされたすべてのエラーを `console.error` に記録します。この動作をオーバーライドするには、省略可能なルートオプションである `onCaughtError` を指定して、[エラーバウンダリ](/reference/react/Component#catching-rendering-errors-with-an-error-boundary)によってキャッチされたエラーを処理するようにします。
-
-```js [[1, 6, "onCaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack"]]
-import { createRoot } from 'react-dom/client';
-
-const root = createRoot(
- document.getElementById('root'),
- {
- onCaughtError: (error, errorInfo) => {
- console.error(
- 'Caught error',
- error,
- errorInfo.componentStack
- );
- }
- }
-);
-root.render();
```
-onCaughtError オプションに指定するのは、以下の 2 つの引数を付けて呼ばれる関数です。
+onCaughtError は以下の 2 つの引数で呼びされる関数です。
-1. バウンダリによってキャッチされた error。
-2. errorInfo オブジェクト。当該エラーの componentStack を含んでいる。
+1. スローされた error。
+2. errorInfo オブジェクト。エラーの componentStack を含んでいる。
-`onCaughtError` ルートオプションを用いて、エラーダイアログを表示したり、既知のエラーをログから除外したりできます。
+`onUncaughtError` と `onRecoverableError` を組み合わせて、独自のエラーレポーティングのシステムを実装できます。
-```html index.html hidden
-
-
-
- My app
-
-
-
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-
-
-
-```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
+```js src/reportError.js
+function reportError({ type, error, errorInfo }) {
+ // The specific implementation is up to you.
+ // `console.error()` is only used for demonstration purposes.
+ console.error(type, error, "Component Stack: ");
+ console.error("Component Stack: ", errorInfo.componentStack);
}
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
-}
-```
-
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
+export function onCaughtErrorProd(error, errorInfo) {
+ if (error.message !== "Known error") {
+ reportError({ type: "Caught", error, errorInfo });
}
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
- }
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
}
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
+export function onUncaughtErrorProd(error, errorInfo) {
+ reportError({ type: "Uncaught", error, errorInfo });
}
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
-}
-
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
+export function onRecoverableErrorProd(error, errorInfo) {
+ reportError({ type: "Recoverable", error, errorInfo });
}
```
```js src/index.js active
import { createRoot } from "react-dom/client";
import App from "./App.js";
-import {reportCaughtError} from "./reportError";
-import "./styles.css";
+import {
+ onCaughtErrorProd,
+ onRecoverableErrorProd,
+ onUncaughtErrorProd,
+} from "./reportError";
const container = document.getElementById("root");
const root = createRoot(container, {
- onCaughtError: (error, errorInfo) => {
- if (error.message !== 'Known error') {
- reportCaughtError({
- error,
- componentStack: errorInfo.componentStack,
- });
- }
- }
+ // Keep in mind to remove these options in development to leverage
+ // React's default handlers or implement your own overlay for development.
+ // The handlers are only specfied unconditionally here for demonstration purposes.
+ onCaughtError: onCaughtErrorProd,
+ onRecoverableError: onRecoverableErrorProd,
+ onUncaughtError: onUncaughtErrorProd,
});
root.render();
```
```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
+import { Component, useState } from "react";
-export default function App() {
- const [error, setError] = useState(null);
-
- function handleUnknown() {
- setError("unknown");
- }
-
- function handleKnown() {
- setError("known");
- }
-
- return (
- <>
- {
- setError(null);
- }}
- >
- {error != null && }
- This error will not show the error dialog:
-
- This error will show the error dialog:
-
-
-
- >
- );
+function Boom() {
+ foo.bar = "baz";
}
-function fallbackRender({ resetErrorBoundary }) {
- return (
-
-
Error Boundary
-
Something went wrong.
-
-
- );
-}
+class ErrorBoundary extends Component {
+ state = { hasError: false };
-function Throw({error}) {
- if (error === "known") {
- throw new Error('Known error')
- } else {
- foo.bar = 'baz';
+ static getDerivedStateFromError(error) {
+ return { hasError: true };
}
-}
-```
-```json package.json hidden
-{
- "dependencies": {
- "react": "19.0.0-rc-3edc000d-20240926",
- "react-dom": "19.0.0-rc-3edc000d-20240926",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
-```
-
-
-
-### 復帰可能なエラーに対するダイアログを表示 {/*displaying-a-dialog-for-recoverable-errors*/}
-
-React はレンダー中にスローされたエラーから復帰するためにコンポーネントを自動的に再度レンダーすることがあります。成功すると、コンソールに復帰可能なエラーについてログを残し、開発者に通知します。この動作をオーバーライドするには、省略可能なルートオプションである `onRecoverableError` を指定します。
-
-```js [[1, 6, "onRecoverableError"], [2, 6, "error", 1], [3, 10, "error.cause"], [4, 6, "errorInfo"], [5, 11, "componentStack"]]
-import { createRoot } from 'react-dom/client';
-
-const root = createRoot(
- document.getElementById('root'),
- {
- onRecoverableError: (error, errorInfo) => {
- console.error(
- 'Recoverable error',
- error,
- error.cause,
- errorInfo.componentStack,
- );
+ render() {
+ if (this.state.hasError) {
+ return Something went wrong.
;
}
+ return this.props.children;
}
-);
-root.render();
-```
-
-onRecoverableError オプションに指定するのは、以下の 2 つの引数を付けて呼ばれる関数です。
-
-1. React たスローした error。一部のエラーは元のエラーを error.cause として含んでいる。
-2. errorInfo オブジェクト。エラーの componentStack を含んでいる。
-
-`onRecoverableError` を用いてエラーダイアログを表示することができます。
-
-
-
-```html index.html hidden
-
-
-
- My app
-
-
-
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-
-
-
-```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
}
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
-}
-```
-
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
- }
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
- }
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
-}
-
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
-}
-
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
-}
-
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
-}
-```
-
-```js src/index.js active
-import { createRoot } from "react-dom/client";
-import App from "./App.js";
-import {reportRecoverableError} from "./reportError";
-import "./styles.css";
-
-const container = document.getElementById("root");
-const root = createRoot(container, {
- onRecoverableError: (error, errorInfo) => {
- reportRecoverableError({
- error,
- cause: error.cause,
- componentStack: errorInfo.componentStack,
- });
- }
-});
-root.render();
-```
-
-```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
-
-// 🚩 Bug: Never do this. This will force an error.
-let errorThrown = false;
export default function App() {
+ const [triggerUncaughtError, settriggerUncaughtError] = useState(false);
+ const [triggerCaughtError, setTriggerCaughtError] = useState(false);
+
return (
<>
-
- {!errorThrown && }
- This component threw an error, but recovered during a second render.
- Since it recovered, no Error Boundary was shown, but onRecoverableError
was used to show an error dialog.
-
-
+
+ {triggerUncaughtError && }
+
+ {triggerCaughtError && (
+
+
+
+ )}
>
);
}
-
-function fallbackRender() {
- return (
-
-
Error Boundary
-
Something went wrong.
-
- );
-}
-
-function Throw({error}) {
- // Simulate an external value changing during concurrent render.
- errorThrown = true;
- foo.bar = 'baz';
-}
-```
-
-```json package.json hidden
-{
- "dependencies": {
- "react": "19.0.0-rc-3edc000d-20240926",
- "react-dom": "19.0.0-rc-3edc000d-20240926",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
```
-
----
## トラブルシューティング {/*troubleshooting*/}
### ルートを作成したが何も表示されない {/*ive-created-a-root-but-nothing-is-displayed*/}
diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md
index aa126b296..eb8e81427 100644
--- a/src/content/reference/react-dom/client/hydrateRoot.md
+++ b/src/content/reference/react-dom/client/hydrateRoot.md
@@ -270,7 +270,7 @@ export default function App() {
-これは単一レベルの深さまでしか機能せず、避難ハッチとしての使用を意図しています。過度に使用しないでください。これを使用してもテキストコンテンツ以外の場合は React は違いを修正しようとはしないため、将来の更新まで一貫性が保たれない可能性があります。
+これは単一レベルの深さまでしか機能せず、避難ハッチとしての使用を意図しています。過度に使用しないでください。これを使用しても React はテキストコンテンツの不一致を修正しようとは**しません**。
---
@@ -374,555 +374,125 @@ export default function App({counter}) {
ハイドレーションされたルートで [`root.render`](#root-render) を呼び出すことは滅多にありません。通常、代わりにコンポーネントの中で [state を更新](/reference/react/useState) します。
-### キャッチされないエラーに対するダイアログを表示 {/*show-a-dialog-for-uncaught-errors*/}
+### 本番環境でのエラーのロギング {/*error-logging-in-production*/}
-デフォルトでは React は、キャッチされなかったエラーをコンソールにログとして表示します。独自のエラーレポーティングを実装するには、省略可能なルートオプションである `onUncaughtError` を指定します。
+デフォルトでは、React はすべてのエラーをコンソールに記録します。独自のエラーレポートの仕組みを実装するには、省略可能なルートオプションとして `onUncaughtError`、`onCaughtError`、`onRecoverableError` のエラーハンドラを提供することができます。
-```js [[1, 7, "onUncaughtError"], [2, 7, "error", 1], [3, 7, "errorInfo"], [4, 11, "componentStack"]]
-import { hydrateRoot } from 'react-dom/client';
+```js [[1, 6, "onCaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack", 15]]
+import { hydrateRoot } from "react-dom/client";
+import { reportCaughtError } from "./reportError";
-const root = hydrateRoot(
- document.getElementById('root'),
- ,
- {
- onUncaughtError: (error, errorInfo) => {
- console.error(
- 'Uncaught error',
+const container = document.getElementById("root");
+const root = hydrateRoot(container, {
+ onCaughtError: (error, errorInfo) => {
+ if (error.message !== "Known error") {
+ reportCaughtError({
error,
- errorInfo.componentStack
- );
+ componentStack: errorInfo.componentStack,
+ });
}
- }
-);
-root.render();
+ },
+});
```
-onUncaughtError オプションに指定するのは、以下の 2 つの引数を付けて呼ばれる関数です。
+onCaughtError は以下の 2 つの引数で呼びされる関数です。
1. スローされた error。
2. errorInfo オブジェクト。エラーの componentStack を含んでいる。
-エラーダイアログを表示するために `onUncaughtError` ルートオプションを用いることが可能です。
+`onUncaughtError` と `onRecoverableError` を組み合わせて、独自のエラーレポーティングのシステムを実装できます。
-```html index.html hidden
-
-
-
- My app
-
-
-
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-This error shows the error dialog:
-
-
-```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
+```js src/reportError.js
+function reportError({ type, error, errorInfo }) {
+ // The specific implementation is up to you.
+ // `console.error()` is only used for demonstration purposes.
+ console.error(type, error, "Component Stack: ");
+ console.error("Component Stack: ", errorInfo.componentStack);
}
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
-}
-```
-
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
- }
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
+export function onCaughtErrorProd(error, errorInfo) {
+ if (error.message !== "Known error") {
+ reportError({ type: "Caught", error, errorInfo });
}
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
-}
-
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
}
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
+export function onUncaughtErrorProd(error, errorInfo) {
+ reportError({ type: "Uncaught", error, errorInfo });
}
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
+export function onRecoverableErrorProd(error, errorInfo) {
+ reportError({ type: "Recoverable", error, errorInfo });
}
```
```js src/index.js active
import { hydrateRoot } from "react-dom/client";
import App from "./App.js";
-import {reportUncaughtError} from "./reportError";
-import "./styles.css";
-import {renderToString} from 'react-dom/server';
+import {
+ onCaughtErrorProd,
+ onRecoverableErrorProd,
+ onUncaughtErrorProd,
+} from "./reportError";
const container = document.getElementById("root");
-const root = hydrateRoot(container, , {
- onUncaughtError: (error, errorInfo) => {
- if (error.message !== 'Known error') {
- reportUncaughtError({
- error,
- componentStack: errorInfo.componentStack
- });
- }
- }
+hydrateRoot(container, , {
+ // Keep in mind to remove these options in development to leverage
+ // React's default handlers or implement your own overlay for development.
+ // The handlers are only specfied unconditionally here for demonstration purposes.
+ onCaughtError: onCaughtErrorProd,
+ onRecoverableError: onRecoverableErrorProd,
+ onUncaughtError: onUncaughtErrorProd,
});
```
```js src/App.js
-import { useState } from 'react';
-
-export default function App() {
- const [throwError, setThrowError] = useState(false);
-
- if (throwError) {
- foo.bar = 'baz';
- }
-
- return (
-
- This error shows the error dialog:
-
-
- );
-}
-```
-
-
-
-
-### エラーバウンダリでキャッチしたエラーを表示 {/*displaying-error-boundary-errors*/}
-
-デフォルトでは、React はエラーバウンダリによってキャッチされたすべてのエラーを `console.error` に記録します。この動作をオーバーライドするには、省略可能なルートオプションである `onCaughtError` を指定して、[エラーバウンダリ](/reference/react/Component#catching-rendering-errors-with-an-error-boundary)によってキャッチされたエラーを処理するようにします。
-
-```js [[1, 7, "onCaughtError"], [2, 7, "error", 1], [3, 7, "errorInfo"], [4, 11, "componentStack"]]
-import { hydrateRoot } from 'react-dom/client';
-
-const root = hydrateRoot(
- document.getElementById('root'),
- ,
- {
- onCaughtError: (error, errorInfo) => {
- console.error(
- 'Caught error',
- error,
- errorInfo.componentStack
- );
- }
- }
-);
-root.render();
-```
-
-onCaughtError オプションに指定するのは、以下の 2 つの引数を付けて呼ばれる関数です。
-
-1. バウンダリによってキャッチされた error。
-2. errorInfo オブジェクト。当該エラーの componentStack を含んでいる。
-
-`onCaughtError` ルートオプションを用いて、エラーダイアログを表示したり、既知のエラーをログから除外したりできます。
-
-
-
-```html index.html hidden
-
-
-
- My app
-
-
-
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-This error will not show the error dialog:This error will show the error dialog:
-
-
-```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
+import { Component, useState } from "react";
-.mb-0 {
- margin-bottom: 0;
+function Boom() {
+ foo.bar = "baz";
}
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
-}
-```
+class ErrorBoundary extends Component {
+ state = { hasError: false };
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
+ static getDerivedStateFromError(error) {
+ return { hasError: true };
}
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
- }
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
- }
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
-}
-
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
-}
-
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
-}
-
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
-}
-```
-
-```js src/index.js active
-import { hydrateRoot } from "react-dom/client";
-import App from "./App.js";
-import {reportCaughtError} from "./reportError";
-import "./styles.css";
-
-const container = document.getElementById("root");
-const root = hydrateRoot(container, , {
- onCaughtError: (error, errorInfo) => {
- if (error.message !== 'Known error') {
- reportCaughtError({
- error,
- componentStack: errorInfo.componentStack
- });
+ render() {
+ if (this.state.hasError) {
+ return Something went wrong.
;
}
+ return this.props.children;
}
-});
-```
-
-```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
+}
export default function App() {
- const [error, setError] = useState(null);
-
- function handleUnknown() {
- setError("unknown");
- }
+ const [triggerUncaughtError, settriggerUncaughtError] = useState(false);
+ const [triggerCaughtError, setTriggerCaughtError] = useState(false);
- function handleKnown() {
- setError("known");
- }
-
return (
<>
- {
- setError(null);
- }}
- >
- {error != null && }
- This error will not show the error dialog:
-
- This error will show the error dialog:
-
-
-
+
+ {triggerUncaughtError && }
+
+ {triggerCaughtError && (
+
+
+
+ )}
>
);
}
-
-function fallbackRender({ resetErrorBoundary }) {
- return (
-
-
Error Boundary
-
Something went wrong.
-
-
- );
-}
-
-function Throw({error}) {
- if (error === "known") {
- throw new Error('Known error')
- } else {
- foo.bar = 'baz';
- }
-}
```
-```json package.json hidden
-{
- "dependencies": {
- "react": "19.0.0-rc-3edc000d-20240926",
- "react-dom": "19.0.0-rc-3edc000d-20240926",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
-```
-
-
-
-### 復帰可能なハイドレーション不一致エラーに対するダイアログを表示 {/*show-a-dialog-for-recoverable-hydration-mismatch-errors*/}
-
-React がハイドレーション時に不一致を検出した場合、自動的にクライアント側でレンダーの復帰をを試みます。デフォルトでは、ハイドレーション不一致に関するエラーは `console.error` に記録されます。この動作をオーバーライドするには、省略可能なルートオプションである `onRecoverableError` を指定します。
-
-```js [[1, 7, "onRecoverableError"], [2, 7, "error", 1], [3, 11, "error.cause", 1], [4, 7, "errorInfo"], [5, 12, "componentStack"]]
-import { hydrateRoot } from 'react-dom/client';
-
-const root = hydrateRoot(
- document.getElementById('root'),
- ,
- {
- onRecoverableError: (error, errorInfo) => {
- console.error(
- 'Caught error',
- error,
- error.cause,
- errorInfo.componentStack
- );
- }
- }
-);
-```
-
-onRecoverableError オプションに指定するのは、以下の 2 つの引数を付けて呼ばれる関数です。
-
-1. React たスローした error。一部のエラーは元のエラーを error.cause として含んでいる。
-2. errorInfo オブジェクト。エラーの componentStack を含んでいる。
-
-`onRecoverableError` を用いてハイドレーション不一致に関するエラーダイアログを表示することができます。
-
-
-
-```html index.html hidden
+```html public/index.html hidden
@@ -930,229 +500,15 @@ const root = hydrateRoot(
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-Server
+Server content before hydration.
```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
-}
-```
-
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
- }
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
- }
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
-}
-
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
-}
-
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
-}
-
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
-}
-```
-
-```js src/index.js active
-import { hydrateRoot } from "react-dom/client";
-import App from "./App.js";
-import {reportRecoverableError} from "./reportError";
-import "./styles.css";
-
-const container = document.getElementById("root");
-const root = hydrateRoot(container, , {
- onRecoverableError: (error, errorInfo) => {
- reportRecoverableError({
- error,
- cause: error.cause,
- componentStack: errorInfo.componentStack
- });
- }
-});
-```
-
-```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
-
-export default function App() {
- const [error, setError] = useState(null);
-
- function handleUnknown() {
- setError("unknown");
- }
-
- function handleKnown() {
- setError("known");
- }
-
- return (
- {typeof window !== 'undefined' ? 'Client' : 'Server'}
- );
-}
-
-function fallbackRender({ resetErrorBoundary }) {
- return (
-
-
Error Boundary
-
Something went wrong.
-
-
- );
-}
-
-function Throw({error}) {
- if (error === "known") {
- throw new Error('Known error')
- } else {
- foo.bar = 'baz';
- }
-}
-```
-
-```json package.json hidden
-{
- "dependencies": {
- "react": "19.0.0-rc-3edc000d-20240926",
- "react-dom": "19.0.0-rc-3edc000d-20240926",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
-```
-
-## Troubleshooting {/*troubleshooting*/}
+## トラブルシューティング {/*troubleshooting*/}
### "You passed a second argument to root.render" というエラーが出る {/*im-getting-an-error-you-passed-a-second-argument-to-root-render*/}
diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md
index 4c3437513..8f3daa6c7 100644
--- a/src/content/reference/react-dom/components/form.md
+++ b/src/content/reference/react-dom/components/form.md
@@ -214,7 +214,7 @@ export default function App() {
]);
async function sendMessage(formData) {
const sentMessage = await deliverMessage(formData.get("message"));
- setMessages([...messages, { text: sentMessage }]);
+ setMessages((messages) => [...messages, { text: sentMessage }]);
}
return ;
}
diff --git a/src/content/reference/react-dom/components/input.md b/src/content/reference/react-dom/components/input.md
index 39f8b410f..44ee0ac61 100644
--- a/src/content/reference/react-dom/components/input.md
+++ b/src/content/reference/react-dom/components/input.md
@@ -297,7 +297,7 @@ input { margin: 5px; }
-デフォルトでは、`
diff --git a/src/content/reference/react-dom/components/style.md b/src/content/reference/react-dom/components/style.md
index aa9c9641d..e8025514e 100644
--- a/src/content/reference/react-dom/components/style.md
+++ b/src/content/reference/react-dom/components/style.md
@@ -49,9 +49,10 @@ React は `