`.
- Usually, you will use refs for non-destructive actions like focusing, scrolling, or measuring DOM elements.
-- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using `forwardRef` and passing the second `ref` argument down to a specific node.
+- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using the `ref` prop.
- Avoid changing DOM nodes managed by React.
- If you do modify DOM nodes managed by React, modify parts that React has no reason to update.
@@ -1117,7 +1049,7 @@ Make it so that clicking the "Search" button puts focus into the field. Note tha
-You'll need `forwardRef` to opt into exposing a DOM node from your own component like `SearchInput`.
+You'll need to pass `ref` as a prop to opt into exposing a DOM node from your own component like `SearchInput`.
@@ -1202,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/react-developer-tools.md b/src/content/learn/react-developer-tools.md
index 377e261b5..e56d5581f 100644
--- a/src/content/learn/react-developer-tools.md
+++ b/src/content/learn/react-developer-tools.md
@@ -56,6 +56,7 @@ react-devtools

+<<<<<<< HEAD
## الهواتف (React Native) {/*mobile-react-native*/}
يمكن استخدام أدوات مطوري React لفحص التطبيقات المبنية بـ [React Native](https://reactnative.dev/).
@@ -65,11 +66,15 @@ react-devtools
```bash
# Yarn
yarn global add react-devtools
+=======
+## Mobile (React Native) {/*mobile-react-native*/}
-# Npm
-npm install -g react-devtools
-```
+To inspect apps built with [React Native](https://reactnative.dev/), you can use [React Native DevTools](https://reactnative.dev/docs/react-native-devtools), the built-in debugger that deeply integrates React Developer Tools. All features work identically to the browser extension, including native element highlighting and selection.
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
+
+[Learn more about debugging in React Native.](https://reactnative.dev/docs/debugging)
+<<<<<<< HEAD
ثم افتح أدوات المطور في موجه الأوامر (Terminal):
```bash
@@ -81,3 +86,6 @@ react-devtools
> جرب إعادة تحميل التطبيق إن لم تتصل أدوات المطور بعد ثوانٍ.
[تعرّف على المزيد حول تصحيح أخطاء React Native](https://reactnative.dev/docs/debugging).
+=======
+> For versions of React Native earlier than 0.76, please use the standalone build of React DevTools by following the [Safari and other browsers](#safari-and-other-browsers) guide above.
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
diff --git a/src/content/learn/render-and-commit.md b/src/content/learn/render-and-commit.md
index eb812b39f..ff22b2d8e 100644
--- a/src/content/learn/render-and-commit.md
+++ b/src/content/learn/render-and-commit.md
@@ -76,9 +76,15 @@ export default function Image() {
بمجرد أن يتم تصيير المكون لأول مرة، يمكنك تنشيط عمليات التصيير الأخرى عن طريق تحديث حالته باستخدام دالة [`set`](/reference/react/useState#setstate). تحديث حالة المكون الخاص بك يضع تلقائيًا عملية تصيير في قائمة الانتظار. (يمكنك تخيل هذه العمليات على أنها طلبات من زبون المطعم للحصول على الشاي أو الحلويات أو أي شيء آخر بعد طلبه الأول، اعتمادًا على حالة عطشه أو جوعه.)
+<<<<<<< HEAD
+=======
+
+
+
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
## الخطوة الثانية: يقوم React بتصيير مكوناتك {/*step-2-react-renders-your-components*/}
@@ -90,7 +96,11 @@ export default function Image() {
هذه العملية تتكرر: إذا كان المكون المحدث يعيد مكونًا آخر، فسيقوم React بتصيير هذا المكون التالي، وإذا كان هذا المكون أيضًا يعيد شيئًا ما، فسيقوم بتصيير هذا المكون التالي، وهكذا. ستستمر العملية حتى لا تكون هناك مكونات متداخلة أخرى ويعرف React بالضبط ما يجب عرضه على الشاشة.
+<<<<<<< HEAD
في المثال التالي، سينفذ React `Gallery()` و `Image()` عدة مرات:
+=======
+In the following example, React will call `Gallery()` and `Image()` several times:
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
@@ -154,10 +164,17 @@ img { margin: 0 10px 10px 0; }
## الخطوة الثالثة: يؤكد React التغييرات على DOM {/*step-3-react-commits-changes-to-the-dom*/}
+<<<<<<< HEAD
بعد تصيير (استدعاء) للمكونات، سيعدل React الـ DOM.
* **أثناء التصيير المبدئي** سيستخدمReact [DOM API `appendChild()`](https://developer.mozilla.org/docs/Web/API/Node/appendChild) لوضع جميع عناصر DOM التي أنشأها على الشاشة.
* **أثناء إعادة التصيير** سينفذ React العمليات اللازمة (التي تم حسابها أثناء التصيير!) لجعل DOM يتطابق مع أحدث نتيجة تصيير.
+=======
+After rendering (calling) your components, React will modify the DOM.
+
+* **For the initial render,** React will use the [`appendChild()`](https://developer.mozilla.org/docs/Web/API/Node/appendChild) DOM API to put all the DOM nodes it has created on screen.
+* **For re-renders,** React will apply the minimal necessary operations (calculated while rendering!) to make the DOM match the latest rendering output.
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
**يغيّر React عناصر DOM فقط إذا كان هناك فرق بين التصييرين.** على سبيل المثال، هناك مكون يقوم بإعادة التصيير مع اختلاف الخصائص المُمَرَّرة من المكون الأصلي كل ثانية. لاحظ كيف يمكنك إضافة بعض النص إلى ``، وتحديث `value`، ولكن النص لا يختفي عند إعادة تصيير المكون:
diff --git a/src/content/learn/setup.md b/src/content/learn/setup.md
new file mode 100644
index 000000000..2c46ee148
--- /dev/null
+++ b/src/content/learn/setup.md
@@ -0,0 +1,28 @@
+---
+title: Setup
+---
+
+
+React integrates with tools like editors, TypeScript, browser extensions, and compilers. This section will help you get your environment set up.
+
+
+
+## Editor Setup {/*editor-setup*/}
+
+See our [recommended editors](/learn/editor-setup) and learn how to set them up to work with React.
+
+## Using TypeScript {/*using-typescript*/}
+
+TypeScript is a popular way to add type definitions to JavaScript codebases. [Learn how to integrate TypeScript into your React projects](/learn/typescript).
+
+## React Developer Tools {/*react-developer-tools*/}
+
+React Developer Tools is a browser extension that can inspect React components, edit props and state, and identify performance problems. Learn how to install it [here](learn/react-developer-tools).
+
+## React Compiler {/*react-compiler*/}
+
+React Compiler is a tool that automatically optimizes your React app. [Learn more](/learn/react-compiler).
+
+## Next steps {/*next-steps*/}
+
+Head to the [Quick Start](/learn) guide for a tour of the most important React concepts you will encounter every day.
diff --git a/src/content/learn/state-a-components-memory.md b/src/content/learn/state-a-components-memory.md
index 75a1fd0b9..73d46bdab 100644
--- a/src/content/learn/state-a-components-memory.md
+++ b/src/content/learn/state-a-components-memory.md
@@ -1452,7 +1452,7 @@ If your linter is [configured for React](/learn/editor-setup#linting), you shoul
#### Remove unnecessary state {/*remove-unnecessary-state*/}
-When the button is clicked, this example should ask for the user's name and then display an alert greeting them. You tried to use state to keep the name, but for some reason it always shows "Hello, !".
+When the button is clicked, this example should ask for the user's name and then display an alert greeting them. You tried to use state to keep the name, but for some reason the first time it shows "Hello, !", and then "Hello, [name]!" with the previous input every time after.
To fix this code, remove the unnecessary state variable. (We will discuss about [why this didn't work](/learn/state-as-a-snapshot) later.)
diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md
index a4ddeb807..320ce74a3 100644
--- a/src/content/learn/tutorial-tic-tac-toe.md
+++ b/src/content/learn/tutorial-tic-tac-toe.md
@@ -296,7 +296,11 @@ export default function Square() {
}
```
+<<<<<<< HEAD
قسم المتصفح يجب أن يعرض زرًا فيه X فيه مثل هذا:
+=======
+The _browser_ section should be displaying a square with an X in it like this:
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7

@@ -1351,7 +1355,11 @@ body {
1. تستخدم `handleClick` الوسيطة (`0`) لتحديث العنصر الأول في مصفوفة `squares` من `null` إلى `X`.
1. تم تحديث حالة `squares` في عنصر ``، لذا يتم إعادة تقديم العنصر `` وجميع عناصره الفرعية. وهذا يؤدي إلى تغيير خاصية `value` لعنصر `` ذي الترتيب `0` من `null` إلى `X`.
+<<<<<<< HEAD
في النهاية يرى المستخدم أن المربع الأيسر العلوي قد تغير من فارغ إلى `X` بعد النقر عليه.
+=======
+In the end the user sees that the upper left square has changed from empty to having an `X` after clicking it.
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
@@ -1432,7 +1440,11 @@ export default function Board() {
الـ `X` تمت الكتابة فوقها بـ `O`! بينما سيضيف هذا لمسة مثيرة للعبة، لكننا سنلتزم بالقواعد الأصلية الآن.
+<<<<<<< HEAD
عندما تحدد مربع بـ `X` أو `O` فأنت لا تتحقق أولاً مما إذا كان المربع يحتوي بالفعل على قيمة `X` أو `O`. يمكنك إصلاح هذا عن طريق *الخروج مبكرًا*. ستتحقق مما إذا كان المربع يحتوي بالفعل على `X` أو `O`. إذا كان المربع ممتلئًا بالفعل، فستقوم بـ `return` في دالة `handleClick` مبكرًا - قبل محاولة تحديث حالة اللوحة.
+=======
+When you mark a square with an `X` or an `O` you aren't first checking to see if the square already has an `X` or `O` value. You can fix this by *returning early*. You'll check to see if the square already has an `X` or an `O`. If the square is already filled, you will `return` in the `handleClick` function early--before it tries to update the board state.
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
```js {2,3,4}
function handleClick(i) {
@@ -1583,7 +1595,11 @@ function calculateWinner(squares) {
+<<<<<<< HEAD
ستنادي دالة `calculateWinner(squares)` في دالة `handleClick` الخاصة بمكون `Board` للتحقق مما إذا كان اللاعب قد فاز. يمكنك تنفيذ هذا التحقق في نفس الوقت الذي تتحقق فيه مما إذا كان المستخدم قد نقر على مربع يحتوي بالفعل على `X` أو `O`. نود أن نوقف تنفيذ الدالة في كلا الحالتين:
+=======
+You will call `calculateWinner(squares)` in the `Board` component's `handleClick` function to check if a player has won. You can perform this check at the same time you check if a user has clicked a square that already has an `X` or an `O`. We'd like to return early in both cases:
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
```js {2}
function handleClick(i) {
diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md
index 593d6bba8..e99136321 100644
--- a/src/content/reference/react-dom/client/createRoot.md
+++ b/src/content/reference/react-dom/client/createRoot.md
@@ -45,8 +45,8 @@ root.render();
* `options` **اختياري**: كائن يحتوي على خيارات لجذر React هذا.
- * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`.
- * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown, and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown, and an `errorInfo` object containing the `componentStack`.
* **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. Called with an `error` React throws, and an `errorInfo` object containing the `componentStack`. Some recoverable errors may include the original error cause as `error.cause`.
* **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page.
@@ -146,7 +146,7 @@ root.render();
-```html index.html
+```html public/index.html
تطبيقي
@@ -346,799 +346,134 @@ export default function App({counter}) {
من غير الشائع أن تستدعي `render` عدة مرات. عادةً، يمكن لمكوناتك [تحديث الحالة](/reference/react/useState) بدلاً من ذلك.
-### Show a dialog for uncaught errors {/*show-a-dialog-for-uncaught-errors*/}
-
-
-
-`onUncaughtError` is only available in the latest React Canary release.
-
-
-
-By default, React will log all uncaught errors to the console. To implement your own error reporting, you can provide the optional `onUncaughtError` root option:
-
-```js [[1, 6, "onUncaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack"]]
-import { createRoot } from 'react-dom/client';
-
-const root = createRoot(
- document.getElementById('root'),
- {
- onUncaughtError: (error, errorInfo) => {
- console.error(
- 'Uncaught error',
- error,
- errorInfo.componentStack
- );
- }
- }
-);
-root.render();
-```
-
-The onUncaughtError option is a function called with two arguments:
-
-1. The error that was thrown.
-2. An errorInfo object that contains the componentStack of the error.
-
-You can use the `onUncaughtError` root option to display error dialogs:
+### Error logging in production {/*error-logging-in-production*/}
-
+By default, React will log all errors to the console. To implement your own error reporting, you can provide the optional error handler root options `onUncaughtError`, `onCaughtError` and `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
+```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:
-
-
- );
-}
-```
-
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0"
},
- "main": "/index.js"
-}
-```
-
-
-
-
-### Displaying Error Boundary errors {/*displaying-error-boundary-errors*/}
-
-
-
-`onCaughtError` is only available in the latest React Canary release.
-
-
-
-By default, React will log all errors caught by an Error Boundary to `console.error`. To override this behavior, you can provide the optional `onCaughtError` root option to handle errors caught by an [Error Boundary](/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();
+});
```
The onCaughtError option is a function called with two arguments:
-1. The error that was caught by the boundary.
+1. The error that was thrown.
2. An errorInfo object that contains the componentStack of the error.
-You can use the `onCaughtError` root option to display error dialogs or filter known errors from logging:
+Together with `onUncaughtError` and `onRecoverableError`, you can can implement your own error reporting system:
-```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;
+```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);
}
-.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 { 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": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
-```
-
-
-### Displaying a dialog for recoverable errors {/*displaying-a-dialog-for-recoverable-errors*/}
-
-React may automatically render a component a second time to attempt to recover from an error thrown in render. If successful, React will log a recoverable error to the console to notify the developer. To override this behavior, you can provide the optional `onRecoverableError` root option:
-
-```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();
-```
-
-The onRecoverableError option is a function called with two arguments:
-
-1. The error that React throws. Some errors may include the original cause as error.cause.
-2. An errorInfo object that contains the componentStack of the error.
-
-You can use the `onRecoverableError` root option to display error dialogs:
-
-
-
-```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": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
```
+<<<<<<< HEAD
---
## حل المشكلات {/*troubleshooting*/}
+=======
+## Troubleshooting {/*troubleshooting*/}
+>>>>>>> fc29603434ec04621139738f4740caed89d659a7
### لقد أنشأت جذرًا، ولكن لا يتم عرض أي شيء {/*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 1ffc094d5..b9348b333 100644
--- a/src/content/reference/react-dom/client/hydrateRoot.md
+++ b/src/content/reference/react-dom/client/hydrateRoot.md
@@ -41,8 +41,8 @@ React will attach to the HTML that exists inside the `domNode`, and take over ma
* **optional** `options`: An object with options for this React root.
- * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`.
- * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown and an `errorInfo` object containing the `componentStack`.
* **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. Called with the `error` React throws, and an `errorInfo` object containing the `componentStack`. Some recoverable errors may include the original error cause as `error.cause`.
* **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as used on the server.
@@ -374,578 +374,125 @@ export default function App({counter}) {
It is uncommon to call [`root.render`](#root-render) on a hydrated root. Usually, you'll [update state](/reference/react/useState) inside one of the components instead.
-### Show a dialog for uncaught errors {/*show-a-dialog-for-uncaught-errors*/}
+### Error logging in production {/*error-logging-in-production*/}
-
+By default, React will log all errors to the console. To implement your own error reporting, you can provide the optional error handler root options `onUncaughtError`, `onCaughtError` and `onRecoverableError`:
-`onUncaughtError` is only available in the latest React Canary release.
-
-
-
-By default, React will log all uncaught errors to the console. To implement your own error reporting, you can provide the optional `onUncaughtError` root option:
-
-```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();
+ },
+});
```
-The onUncaughtError option is a function called with two arguments:
+The onCaughtError option is a function called with two arguments:
1. The error that was thrown.
2. An errorInfo object that contains the componentStack of the error.
-You can use the `onUncaughtError` root option to display error dialogs:
+Together with `onUncaughtError` and `onRecoverableError`, you can implement your own error reporting system:
-```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;
-}
-
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
+```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);
}
-```
-```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 = '';
+export function onCaughtErrorProd(error, errorInfo) {
+ if (error.message !== "Known error") {
+ reportError({ type: "Caught", error, errorInfo });
}
-
- // 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 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';
+import { Component, useState } from "react";
-export default function App() {
- const [throwError, setThrowError] = useState(false);
-
- if (throwError) {
- foo.bar = 'baz';
- }
-
- return (
-
- This error shows the error dialog:
-
-
- );
+function Boom() {
+ foo.bar = "baz";
}
-```
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0"
- },
- "main": "/index.js"
-}
-```
-
-
-
-
-### Displaying Error Boundary errors {/*displaying-error-boundary-errors*/}
-
-
+class ErrorBoundary extends Component {
+ state = { hasError: false };
-`onCaughtError` is only available in the latest React Canary release.
-
-
-
-By default, React will log all errors caught by an Error Boundary to `console.error`. To override this behavior, you can provide the optional `onCaughtError` root option for errors caught by an [Error Boundary](/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
- );
- }
+ static getDerivedStateFromError(error) {
+ return { hasError: true };
}
-);
-root.render();
-```
-
-The onCaughtError option is a function called with two arguments:
-
-1. The error that was caught by the boundary.
-2. An errorInfo object that contains the componentStack of the error.
-You can use the `onCaughtError` root option to display error dialogs or filter known errors from logging:
-
-
-
-```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;
-}
-
-.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 {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": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
```
-
-
-### Show a dialog for recoverable hydration mismatch errors {/*show-a-dialog-for-recoverable-hydration-mismatch-errors*/}
-
-When React encounters a hydration mismatch, it will automatically attempt to recover by rendering on the client. By default, React will log hydration mismatch errors to `console.error`. To override this behavior, you can provide the optional `onRecoverableError` root option:
-
-```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
- );
- }
- }
-);
-```
-
-The onRecoverableError option is a function called with two arguments:
-
-1. The error React throws. Some errors may include the original cause as error.cause.
-2. An errorInfo object that contains the componentStack of the error.
-
-You can use the `onRecoverableError` root option to display error dialogs for hydration mismatches:
-
-
-
-```html index.html hidden
+```html public/index.html hidden
@@ -953,226 +500,12 @@ You can use the `onRecoverableError` root option to display error dialogs for hy
-
-
-
-
-
-
-
-
-
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": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
-```
-
## Troubleshooting {/*troubleshooting*/}
diff --git a/src/content/reference/react-dom/components/common.md b/src/content/reference/react-dom/components/common.md
index 62ee08139..9d1533213 100644
--- a/src/content/reference/react-dom/components/common.md
+++ b/src/content/reference/react-dom/components/common.md
@@ -246,43 +246,41 @@ These events fire for resources like [`