hydrateRoot
تمكنك hydrateRoot
من عرض مكونات React في عناصر DOM التي تم توليدها سابقًا باستخدام react-dom/server
في المتصفح.
const root = hydrateRoot(domNode, reactNode, options?)
المرجع
hydrateRoot(domNode, reactNode, options?)
استدعِ hydrateRoot
لـ “ربط” React بـ HTML الحالي الذي تم عرضه بالفعل بواسطة React في بيئة الخادم.
import { hydrateRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = hydrateRoot(domNode, reactNode);
سيقوم React بربط نفسه بالHTML الموجود داخل الـ domNode
والاهتمام بإدارة DOM داخلها. التطبيق المبنى كاملًا بواسطة React سيكون لديه عادة استدعاء واحد فقط لـ hydrateRoot
باستخدام مكوِّن الجذر الخاص به.
المعاملات
-
domNode
: عنصر DOM الذي تم عرضه كعنصر جذر على الخادم. -
reactNode
: “مُكوِّن React” المستخدم لعرض HTML الحالي. هذا عادةً ما يكون جزءًا من JSX مثل<App />
الذي تم عرضه باستخدام طريقةReactDOM Server
مثلrenderToPipeableStream(<App />)
. -
options
اختياري: كائن يحتوي على خيارات لجذر React هذا.onRecoverableError
اختياري: دالة مرجعية تُستدعى تلقائيًا عندما يفيق React من الأخطاء.identifierPrefix
اختياري: بادئة نصيّة يستخدمها React للمعرفات الفريدة التي تنشأ عن طريقuseId
. مفيد لتجنب التعارض عند استخدام العديد من الجذور في نفس الصفحة.
العائدات
تعيد hydrateRoot
كائنًا يحتوي على طريقتين: render
و unmount
.
ملاحظات
hydrateRoot()
يتوقع أن يكون المحتوى المعروض مطابقًا تمامًا للمحتوى المرسوم في الخادم. يجب عليك التعامل مع عدم التطابقات على أنها أخطاء وإصلاحها.- في وضع التطوير، يحذر React من التطابقات أثناء الربط. لا يوجد ضمانات بأن الاختلافات في السمات ستكون مُصحَّحة في حالة التطابقات. هذا مهم لأسباب أداء لأنه في معظم التطبيقات، يكون الاختلافات نادرة، وبالتالي فإن التحقق من صحة جميع العلامات قد يكون صعبًا جدًا.
- من المرجح أن لديك استدعاء واحد فقط لـ
hydrateRoot
في تطبيقك. إذا كنت تستخدم إطار عمل، فقد يستدعيها الإطار نيابةً عنك. - إذا كان تطبيقك يُرسم في جانب العميل، بدون أي محتوى HTML بالفعل، فاستخدام
hydrateRoot()
ليس مناسبًا. بدلاً من ذلك، استخدمcreateRoot()
.
root.render(reactNode)
استدعِ root.render
لتحديث مكون React داخل جذر React في عنصر DOM في المتصفح.
root.render(<App />);
ستحدث React <App />
في root
المُجَمّع.
المعاملات
reactNode
: عنصر React الذي ترغب في عرضه. عادةً ما يكون هذا جزءًا من JSX مثل<App />
، ولكن يمكنك أيضًا تمرير عنصر React المُنشأ باستخدامcreateElement()
، أو نص أو رقم أوnull
أوundefined
.
العائدات
تعيد root.render
: undefined
.
ملاحظات
- إذا استدعيت
root.render
قبل أن ينتهي الجذر من الربط (hydrating)، فسيقوم React بمسح محتوى HTML المرسوم بالفعل من الخادم وتحويل الجذر بأكمله إلى الرسم من جانب العميل.
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 بعد إلغاء تثبيت الجذر السابقة لذلك العنصر.
الاستخدام
ربط HTML تم رسمه بالخادم
إذا تم إنشاء HTML تطبيقك بواسطة react-dom/server
، فستحتاج إلى ربطه في جانب الخادم.
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);
سيقوم هذا بربط HTML الخادم داخل عنصر DOM المتصفح باستخدام مكوِّن React لتطبيقك. عادةً ما تقوم بفعل ذلك مرة واحدة عند بدء التشغيل. إذا كنت تستخدم إطار عمل ما، فقد يقوم الإطار بعمل هذا الأمر بالنيابة عنك.
بهذه الطريقة، سيقوم React بـ “ربط” منطق المكوِّنات الخاصة بك بالـ HTML الأولي الذي تم إنشاؤه من الخادم. يحول الربطُ نسخة HTML الأولية من الخادم إلى تطبيق متفاعل بالكامل يعمل في المتصفح.
import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot( document.getElementById('root'), <App /> );
لن تحتاج لاستدعاء hydrateRoot
مرة أخرى في أي مكان أخر. من هذه النقطة فصاعدًا، سيقوم React بإدارة DOM لتطبيقك. لتحديث واجهة مستخدم، ستقوم المكوِّنات الخاصة بك باستخدام الحالة بدلاً من ذلك.
ربط مستند بأكمله
يمكن للتطبيقات المُبنَّية بالكامل بواسطة React أن تعرض المستند بأكمله على شكل JSX، بما في ذلك العلامة <html>
:
function App() {
return (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/styles.css"></link>
<title>تطبيقي</title>
</head>
<body>
<Router />
</body>
</html>
);
}
لربط المستند بأكمله، مرر الكائن العام (document
) كأول معامل إلى hydrateRoot
:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document, <App />);
كتم تحذيرات الربط غير المرتبطة بالربط
إذا كان هناك اختلاف ضروري بين سمة عنصر واحد أو محتوى النص بين الخادم والعميل (على سبيل المثال ، الطابع الزمني)، فيمكنك إسكات تحذيرات الربط غير المرتبطة بالربط.
لكتم تحذيرات الربط على عنصر ما، أضف suppressHydrationWarning={true}
:
export default function App() { return ( <h1 suppressHydrationWarning={true}> Current Date: {new Date().toLocaleDateString()} </h1> ); }
هذا يعمل فقط لعنصر واحد عميق، ومقصود أن يكون هروبًا. لا تستخدمه بكثرة. ما لم يكن هو محتوى النص، فإن React لن يحاول تصحيحه، وبالتالي قد يظل غير متسق حتى التحديثات المستقبلية.
التعامل مع محتوى مختلف بين العميل والخادم
إذا كنت بحاجة إلى طرح شيء مختلف عند الخادم والعميل بصورة مقصودة، فيمكنك عمل رسم مرحلتين. يمكن للمكوِّنات التي تقوم بعرض شيء مختلف عند العميل أن تقرأ متغير الحالة مثل isClient
، الذي يمكنك تعيينه على true
في التأثير:
import { useState, useEffect } from "react"; export default function App() { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true); }, []); return ( <h1> {isClient ? 'Is Client' : 'Is Server'} </h1> ); }
بهذه الطريقة، ستقوم عملية الإعادة الأولية بتقديم نفس المحتوى الذي تم تجهيزه على الخادم، مما يمنع حدوث عدم التطابق، لكن سيحدث عبور إضافي بشكل متزامن مباشرة بعد الربط.
تحديث مكون جذري مربوط
بعد الانتهاء من ربط الجذر، يمكنك استدعاء root.render
لتحديث جذر مكون React. خلافًا لاستخدام createRoot
، عادةً لن تحتاج إلى القيام بذلك لأن المحتوى الأولي تم عرضه بالفعل كـ HTML.
إذا استدعيت root.render
في وقت ما بعد الربط، وكانت هيكلة شجرة المكونات مُطابقة لما تم عرضه سابقًا، ستقوم React بالحفاظ على الحالة. لاحظ كيف يمكنك الكتابة في الحقل، مما يعني أن التحديثات من استدعاءات render
المتكررة كل ثانية في هذا المثال لا تؤدي إلى تدمير الحالة:
import { hydrateRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; const root = hydrateRoot( document.getElementById('root'), <App counter={0} /> ); let i = 0; setInterval(() => { root.render(<App counter={i} />); i++; }, 1000);
غالبًا ما يكون استدعاء root.render
على جذر مربوط أمرًا غير معتاد. عادةً، ستقوم بـتحديث الحالة داخل أحد المكونات بدلاً من ذلك.