`.
- 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/passing-data-deeply-with-context.md b/src/content/learn/passing-data-deeply-with-context.md
index 1aea87b35..e81678c8e 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 (
);
}
```
-This tells React: "if any component inside this `
` asks for `LevelContext`, give them this `level`." The component will use the value of the nearest `` in the UI tree above it.
+This tells React: "if any component inside this `` asks for `LevelContext`, give them this `level`." The component will use the value of the nearest `` in the UI tree above it.
@@ -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);
It's the same result as the original code, but you did not need to pass the `level` prop to each `Heading` component! Instead, it "figures out" its heading level by asking the closest `Section` above:
1. You pass a `level` prop to the ``.
-2. `Section` wraps its children into ``.
+2. `Section` wraps its children into ``.
3. `Heading` asks the closest value of `LevelContext` above with `useContext(LevelContext)`.
## Using and providing context from the same component {/*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 @@ In general, if some information is needed by distant components in different par
* To pass context:
1. Create and export it with `export const MyContext = createContext(defaultValue)`.
2. Pass it to the `useContext(MyContext)` Hook to read it in any child component, no matter how deep.
- 3. Wrap children into `
` to provide it from a parent.
+ 3. Wrap children into `` to provide it from a parent.
* Context passes through any components in the middle.
* Context lets you write components that "adapt to their surroundings".
* Before you use context, try passing props or passing JSX as `children`.
@@ -1022,7 +1022,7 @@ li {
Remove `imageSize` prop from all the components.
-Create and export `ImageSizeContext` from `Context.js`. Then wrap the List into `` to pass the value down, and `useContext(ImageSizeContext)` to read it in the `PlaceImage`:
+Create and export `ImageSizeContext` from `Context.js`. Then wrap the List into `` to pass the value down, and `useContext(ImageSizeContext)` to read it in the `PlaceImage`:
@@ -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-developer-tools.md b/src/content/learn/react-developer-tools.md
index 377e261b5..db00a9f92 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.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
+
+[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.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
diff --git a/src/content/learn/render-and-commit.md b/src/content/learn/render-and-commit.md
index eb812b39f..a06750b12 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
+=======
+
+
+
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
## الخطوة الثانية: يقوم 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:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -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.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
**يغيّر 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..3189a68a1 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:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d

@@ -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.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -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.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```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:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```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..440c41907 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*/}
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### لقد أنشأت جذرًا، ولكن لا يتم عرض أي شيء {/*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..9607f3e02 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.
@@ -99,7 +99,7 @@ An app fully built with React will usually not have any calls to `root.unmount`.
This is mostly useful if your React root's DOM node (or any of its ancestors) may get removed from the DOM by some other code. For example, imagine a jQuery tab panel that removes inactive tabs from the DOM. If a tab gets removed, everything inside it (including the React roots inside) would get removed from the DOM as well. You need to tell React to "stop" managing the removed root's content by calling `root.unmount`. Otherwise, the components inside the removed root won't clean up and free up resources like subscriptions.
-Calling `root.unmount` will unmount all the components in the root and "detach" React from the root DOM node, including removing any event handlers or state in the tree.
+Calling `root.unmount` will unmount all the components in the root and "detach" React from the root DOM node, including removing any event handlers or state in the tree.
#### Parameters {/*root-unmount-parameters*/}
@@ -270,7 +270,7 @@ export default function App() {
-This only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates.
+This only works one level deep, and is intended to be an escape hatch. Don’t overuse it. React will **not** attempt to patch mismatched text content.
---
@@ -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 [`