تمكنك createRoot من إنشاء نقطة بداية أو جذر (Root) لعرض مكونات React داخل عنصر DOM في المتصفح.

const root = createRoot(domNode, options?)

المرجع

createRoot(domNode, options?)

استدعِ createRoot لإنشاء جذر React لعرض المحتوى داخل عنصر DOM في المتصفح.

import { createRoot } from 'react-dom/client';

const domNode = document.getElementById('root');
const root = createRoot(domNode);

سيقوم React بإنشاء جذر لـ domNode، ويتولى إدارة العنصر DOM داخله. بعد إنشاء الجذر، يتعين عليك استدعاء root.render لعرض مكون React داخله:

root.render(<App />);

يتم عادة إنشاء التطبيق بالكامل باستخدام React بنداء واحد فقط لـ createRoot في المكون الجذر. قد يحتوي الموقع الذي يستخدم React لأجزاء محددة من الصفحة على عدد من نقاط البداية الفردية حسب الحاجة.

انظر المزيد من الأمثلة أدناه.

المعاملات

  • domNode: عنصر DOM يقوم React بإنشاء جذر لهذا العنصر ويتيح لك استدعاء الدوال على الجذر مثل render لعرض المحتوى الذي تنشئه React.

  • options اختياري: كائن يحتوي على خيارات لجذر React هذا.

    • Canary only 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.
    • Canary only 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. Useful to avoid conflicts when using multiple roots on the same page.

العائدات

يعيد createRoot كائنًا يحتوي على طريقتين: render و unmount.

ملاحظات

  • إذا كان تطبيقك يتم عرضه من الخادم SSR، فإن استخدام createRoot() غير مدعوم. استخدم hydrateRoot() بدلاً من ذلك.
  • من المرجح أن لديك استدعاء واحد فقط لـ createRoot في تطبيقك. إذا كنت تستخدم إطار عمل، فقد يستدعيها الإطار نيابةً عنك.
  • عندما ترغب في عرض جزء من JSX في جزء آخر من شجرة DOM التي ليست طفلًا للمكون الخاص بك (على سبيل المثال، نافذة محادثة، أو توضيح Tooltip)، استخدم createPortal بدلاً من createRoot.

root.render(reactNode)

استدعِ root.render لعرض جزء من JSX (“عنصر React”) داخل عنصر DOM في جذر React.

root.render(<App />);

سيعرض React <App /> في الجذر، وسيتولى إدارة العنصر DOM داخله.

انظر المزيد من الأمثلة أدناه.

المعاملات

  • reactNode: عنصر React الذي ترغب في عرضه. عادةً ما يكون هذا جزءًا من JSX مثل <App />، ولكن يمكنك أيضًا تمرير عنصر React المُنشأ باستخدام createElement()، أو نص أو رقم أو null أو undefined.

العائدات

يعيد root.render undefined.

ملاحظات

  • عندما تستدعي root.render للمرة الأولى، سيحذف React كل المحتوى الموجود داخل جذر React قبل عرض مكونات React فيه.

  • إذا كان جذر عنصر DOM الخاص بك يحتوي على HTML أنشأته React على الخادم أو أثناء البناء، استخدم hydrateRoot() بدلاً من ذلك، والتي تربط مستمعي الأحداث بـ HTML الموجود بالفعل.

  • إذا استدعيت render في نفس الجذر أكثر من مرة، ستحدث React عناصر DOM اللازمة ليظهر أحدث JSX مررتها، ستقرر React أي أجزاء React يمكن إعادة استخدامها، ,أيها يحتاج لإعادة الإنشاء عن طريق “مطابقتها” مع الشجرة المعروضة سابقًا. استدعاء render في نفس الجذر مرة أخرى يشبه مناداة دالة set في المكون الجذر: تتجنب React تحديثات DOM غير الضرورية.


root.unmount()

استدعِ root.unmount لتدمير شجرة معروضة داخل جذر React.

root.unmount();

عادةً، لن يستدعي تطبيق مبني كاملًا بـ React root.unmount.

هذا يكون مفيدًا بشكل أساسي إذا كان عنصر جذر React الخاصة بك (أو أي من العناصر الأسلاف لها) قد يتم إزالتها من DOM بواسطة بعض الأكواد الأخرى. على سبيل المثال، تخيل أن لديك لوحة علامات jQuery تقوم بإزالة علامات غير نشطة من DOM. إذا تمت إزالة علامة ما، فإن كل ما بداخلها (بما في ذلك جذور React الداخلية) سيتم إزالته من DOM أيضًا. في هذه الحالة، تحتاج إلى إخبار React بأنه يجب “إيقاف” إدارة محتوى الجذر المزال عن طريق استدعاء root.unmount. وإلا، فإن المكونات الداخلية في الجذر المزال لن تعرف كيفية التنظيف وتحرير الموارد العامة مثل الاشتراكات.

عند استدعاء root.unmount، سيتم إلغاء تثبيت جميع المكونات في الجذر” و”فصل” React عن عنصر DOM الجذر، بما في ذلك إزالة أي معالجات أحداث أو حالة في الشجرة.

المعاملات

root.unmount لا تستقبل أي معاملات.

العائدات

تعيد root.unmount: undefined.

ملاحظات

  • استدعاء root.unmount سيلغي تثبيت جميع المكونات في الشجرة ويفصل React عن عنصر DOM الجذر.
  • بمجرد استدعاء root.unmount، لا يمكنك استدعاء root.render مرة أخرى على نفس الجذر. ستؤدي محاولة استدعاء root.render على جذر غير مثبتة إلى إطلاق خطأ "Cannot update an unmounted root". ومع ذلك، يمكنك إنشاء جذر جديد لنفس عنصر DOM بعد إلغاء تثبيت الجذر السابقة لذلك العنصر.

الاستخدام

عرض التطبيق المُبني بالكامل بواسطة React

إذا كان تطبيقك مبنيًا بالكامل بواسطة React، قم بإنشاء جذر واحدة لتطبيقك بالكامل.

import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'));
root.render(<App />);

عادةً ما يكون عليك تنفيذ هذا الشيء مرة واحدة فقط عند بدء التشغيل.

سيقوم بما يلي:

  1. العثور على عنصر DOM للمتصفح المعرف في ملف HTML الخاص بك.
  2. عرض مكون React لتطبيقك بداخله.
import { createRoot } from 'react-dom/client';
import App from './App.js';
import './styles.css';

const root = createRoot(document.getElementById('root'));
root.render(<App />);

إذا كان تطبيقك مبنيًا بالكامل بواسطة React، فغالبًا لن تحتاج إلى إنشاء مزيد من الجذور أو استدعاء root.render مرة أخرى.

من هذه النقطة وما بعدها، سيتولى React إدارة DOM للتطبيق بأكمله. لإضافة مكونات إضافية، احتضنها داخل المكون App. عندما تحتاج إلى تحديث واجهة المستخدم، يمكن أن تقوم كل من مكوناتك بذلك عن طريق استخدام الحالة. وعندما تحتاج إلى عرض محتوى إضافي مثل نافذة منبثقة أو نصائح خارج عنصر DOM، اعرضه باستخدام createPortal.

Note

عندما يكون عنصر HTML خاليًا، يرى المستخدم صفحة فارغة حتى يتم تحميل وتشغيل كود JavaScript للتطبيق:

<div id="root"></div>

يمكن أن يكون هذا بطيئًا جدًا! لحل هذه المشكلة، يمكنك إنشاء عنصر HTML الأولي من مكوناتك على الخادم أو أثناء البناء. ثم يمكن لزوار موقعك قراءة النص ورؤية الصور والنقر على الروابط قبل تحميل أي كود JavaScript. نوصي بأن تستخدم إطار عمل يفعل هذا الأمر تلقائيًا. اعتمادًا على موعد تشغيله، يُطلق عليه تحميل من جانب الخادم (SSR) أو توليد المواقع الثابت (SSG).

Pitfall

يجب على التطبيقات التي تستخدم تقنية تصيير الخادم (server rendering) أو التوليد الثابت (static generation) استدعاء hydrateRoot بدلاً من createRoot. سيقوم React بعد ذلك بـ تحييد hydrate (إعادة استخدام) عناصر DOM من HTML الخاص بك بدلاً من تدميرها وإعادة إنشائها.


عرض صفحة مبنية جزئيًا بواسطة React

إذا كانت صفحتك ليست مبنية بالكامل باستخدام React، يمكنك استدعاء createRoot عدة مرات لإنشاء جذر لكل قسم من أقسام واجهة المستخدم الرئيسية التي تُدار بواسطة React. يمكنك عرض محتوى مختلف في كل جذر عن طريق استدعاء root.render.

في هذا المثال، يتم عرض نوعين مختلفين من مُكوِّنات React في عنصري DOM موجودين في ملف index.html:

import './styles.css';
import { createRoot } from 'react-dom/client';
import { Comments, Navigation } from './Components.js';

const navDomNode = document.getElementById('navigation');
const navRoot = createRoot(navDomNode); 
navRoot.render(<Navigation />);

const commentDomNode = document.getElementById('comments');
const commentRoot = createRoot(commentDomNode); 
commentRoot.render(<Comments />);

يمكنك أيضًا إنشاء عنصر DOM جديد باستخدام document.createElement() وإضافتها يدويًا إلى المستند.

const domNode = document.createElement('div');
const root = createRoot(domNode);
root.render(<Comment />);
document.body.appendChild(domNode); // يمكنك إضافتها في أي مكان بالمستند

لإزالة شجرة React من عنصر DOM وتنظيف جميع الموارد المستخدمة من قِبلها، استدعِ root.unmount.

root.unmount();

تعتبر هذه الطريقة مفيدة بشكل رئيسي إذا كانت مُكوِّنات React الخاصة بك داخل تطبيق مكتوب بإطار عمل مختلف.


تحديث المكون الجذر

يمكنك استدعاء render أكثر من مرة على نفس الجذر. طالما أن هيكل شجرة المُكوِّن يُطابق ما تم عرضه سابقًا، ستُحافظ React على الحالة. لاحظ كيف يمكنك كتابة نص في المُدخل، مما يعني أن التحديثات الناتجة عن استدعاءات render المتكررة كل ثانية في هذا المثال لا تُؤدي إلى حذف البيانات:

import { createRoot } from 'react-dom/client';
import './styles.css';
import App from './App.js';

const root = createRoot(document.getElementById('root'));

let i = 0;
setInterval(() => {
  root.render(<App counter={i} />);
  i++;
}, 1000);

من غير الشائع أن تستدعي render عدة مرات. عادةً، يمكن لمكوناتك تحديث الحالة بدلاً من ذلك.

Show a dialog for uncaught errors

Canary

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:

import { createRoot } from 'react-dom/client';

const root = createRoot(
document.getElementById('root'),
{
onUncaughtError: (error, errorInfo) => {
console.error(
'Uncaught error',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);

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:

import { createRoot } from "react-dom/client";
import App from "./App.js";
import {reportUncaughtError} from "./reportError";
import "./styles.css";

const container = document.getElementById("root");
const root = createRoot(container, {
  onUncaughtError: (error, errorInfo) => {
    if (error.message !== 'Known error') {
      reportUncaughtError({
        error,
        componentStack: errorInfo.componentStack
      });
    }
  }
});
root.render(<App />);

Displaying Error Boundary errors

Canary

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:

import { createRoot } from 'react-dom/client';

const root = createRoot(
document.getElementById('root'),
{
onCaughtError: (error, errorInfo) => {
console.error(
'Caught error',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);

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:

import { createRoot } from "react-dom/client";
import App from "./App.js";
import {reportCaughtError} from "./reportError";
import "./styles.css";

const container = document.getElementById("root");
const root = createRoot(container, {
  onCaughtError: (error, errorInfo) => {
    if (error.message !== 'Known error') {
      reportCaughtError({
        error, 
        componentStack: errorInfo.componentStack,
      });
    }
  }
});
root.render(<App />);

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:

import { createRoot } from 'react-dom/client';

const root = createRoot(
document.getElementById('root'),
{
onRecoverableError: (error, errorInfo) => {
console.error(
'Recoverable error',
error,
error.cause,
errorInfo.componentStack,
);
}
}
);
root.render(<App />);

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:

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(<App />);


حل المشكلات

لقد أنشأت جذرًا، ولكن لا يتم عرض أي شيء

تأكد من أنك لم تنسى أن تقوم بـ عرض تطبيقك فعليًا في الجذر:

import { createRoot } from 'react-dom/client';
import App from './App.js';

const root = createRoot(document.getElementById('root'));
root.render(<App />);

إلى أن تفعل ذلك، لن يتم عرض أي شيء.


أواجه خطأ: “You passed a second argument to root.render”

من الأخطاء الشائعة تمرير خيارات createRoot إلى root.render(...):

Console
Warning: You passed a second argument to root.render(…) but it only accepts one argument.

To fix, pass the root options to createRoot(...), not root.render(...):

// 🚩 Wrong: root.render only takes one argument.
root.render(App, {onUncaughtError});

// ✅ Correct: pass options to createRoot.
const root = createRoot(container, {onUncaughtError});
root.render(<App />);

أواجه خطأ: "Target container is not a DOM element"

هذا الخطأ يعني أن ما تقوم بتمريره إلى createRoot ليس عنصر DOM.

إذا لم تكن متأكدًا مما يحدث، جرب استخدام console.log للتحقق من القيمة التي تمررها إلى createRoot:

const domNode = document.getElementById('root');
console.log(domNode); // ???
const root = createRoot(domNode);
root.render(<App />);

على سبيل المثال، إذا كانت domNode تساوي null، فهذا يعني أن getElementById قد أرجع null. وهذا سيحدث إذا لم يكن هناك عنصر في المستند يحمل المعرف ID المعطاة في وقت استدعائك للدالة. قد تكون هناك بعض الأسباب وراء ذلك:

  1. ربما يكون المعرف الذي تبحث عنه مختلف عن المعرف التي استخدمته في ملف HTML. تحقق من الأخطاء الإملائية!
  2. ربما لا يمكن لعنصر <script> الخاص بك “رؤية” أي عنصر DOM تظهر بعده في HTML.

طريقة شائعة أخرى للحصول على هذا الخطأ هي كتابة createRoot(<App />) بدلاً من createRoot(domNode).


أواجه خطأ: "Functions are not valid as a React child."

هذا الخطأ يعني أن ما تمرره إلى root.render ليس مكوِّن React.

قد يحدث هذا إذا قمت باستدعاء root.render باستخدام Component بدلاً من <Component />:

// 🚩 خاطئ: App هي دالة، وليست مكوِّن.
root.render(App);

// ✅ صحيح: <App /> هو مكوِّن.
root.render(<App />);

أو إذا قمت بتمرير دالة إلى root.render بدلاً من نتيجة استدعائها:

// 🚩 خاطئ: createApp هي دالة، وليست مكوِّن.
root.render(createApp);

// ✅ صحيح: قم باستدعاء createApp لترجع مكوِّنًا.
root.render(createApp());

يتم إعادة إنشاء HTML المنشأة بواسطة الخادم من جديد

إذا كان تطبيقك قد تم رسمه بواسطة الخادم ويتضمن HTML الأولي الذي تم إنشاؤه بواسطة React، قد تلاحظ أن إنشاء جذر واستدعاء root.render يحذف كل هذا الHTML، ثم يُعيد إنشاء جميع عناصر DOM من جديد. قد يكون هذا أبطأ، ويؤدي إلى إعادة تعيين التركيز ومواقع التمرير، وقد يؤدي إلى فقدان مدخلات المستخدم الأخرى.

يجب على تطبيقات التي تم رسمها بواسطة الخادم استخدام hydrateRoot بدلاً من createRoot:

import { hydrateRoot } from 'react-dom/client';
import App from './App.js';

hydrateRoot(
document.getElementById('root'),
<App />
);

لاحظ أن واجهة برمجة التطبيقات API مختلفة. عادةً ما لن يكون هناك مزيد من استدعاءات root.render.