| title | التصيير والتأكيد |
|---|
قبل أن يتم عرض مكوناتك في الشاشة، يجب أن يتم تصييرها بواسطة React. فهم الخطوات في هذه العملية سيساعدك على التفكير في كيفية تنفيذ الكود الخاص بك وشرح سلوكه.
- ماذا يعني التصيير في React
- متى ولماذا يقوم React بتصيير مكون
- خطوات عرض مكون في الشاشة
- لماذا التصيير لا يقدم دائمًا تحديث DOM
تخيل أن مكوناتك طهاة في المطبخ، يطبخون وصفات لذيذة، في هذا السيناريو، React هو النادل الذي يسجل طلبات الزبائن ويقدمها لهم. هذه العملية من طلب وتقديم الواجهة لها ثلاث خطوات:
- تنشيط عملية التصيير (تسليم طلب الزبون للمطبخ)
- تصيير المكون (إعداد الطلب في المطبخ)
- التأكيد على DOM (وضع الطلب على الطاولة)
هناك سببان لتنفيذ تصيير المكون:
- التصيير الأوَّلِي للمكون. (initial render)
- تم تحديث حالة المكون (أو أحد آبائه). (state)
عند بدء تشغيل التطبيق، تحتاج لبدء التصيير الأوَّلِي، تخفي إطارات العمل ومحررات الأكواد البسيطة هذا الكود، لكنه يتم بواسطة استدعاء createRoot مستهدفًا عنصر DOM، ثم استدعاء طريقة render مع المكون الخاص بك:
import Image from './Image.js';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'))
root.render(<Image />);export default function Image() {
return (
<img
src="https://i.imgur.com/ZF6s192.jpg"
alt="'Floralis Generica' لإدواردو كاتالانو: منحوتة زهرة معدنية عملاقة بتلات عاكسة للضوء"
/>
);
}جرب عمل تعليق على السطر الذي يستدعي root.render() وانظر كيف تختفي الصورة.
مثل هذا:
// root.render(<Image />);بمجرد أن يتم تصيير المكون لأول مرة، يمكنك تنشيط عمليات التصيير الأخرى عن طريق تحديث حالته باستخدام دالة set. تحديث حالة المكون الخاص بك يضع تلقائيًا عملية تصيير في قائمة الانتظار. (يمكنك تخيل هذه العمليات على أنها طلبات من زبون المطعم للحصول على الشاي أو الحلويات أو أي شيء آخر بعد طلبه الأول، اعتمادًا على حالة عطشه أو جوعه.)
بعد تنشيط عملية التصيير، يقوم React بتصيير مكوناتك لمعرفة ما يجب عرضه على الشاشة. "التصيير" هو استدعاء React لمكوناتك.
- عند التصيير الأوَّلِي، سينشئ React المكون الأصل.
- عند التصيير اللاحق، سينشئ React المكون الذي أدى تحديث حالته إلى التصيير.
هذه العملية تتكرر: إذا كان المكون المحدث يعيد مكونًا آخر، فسيقوم React بتصيير هذا المكون التالي، وإذا كان هذا المكون أيضًا يعيد شيئًا ما، فسيقوم بتصيير هذا المكون التالي، وهكذا. ستستمر العملية حتى لا تكون هناك مكونات متداخلة أخرى ويعرف React بالضبط ما يجب عرضه على الشاشة.
في المثال التالي، سينفذ React Gallery() و Image() عدة مرات:
export default function Gallery() {
return (
<section>
<h1>منحوتات ملهمة</h1>
<Image />
<Image />
<Image />
</section>
);
}
function Image() {
return (
<img
src="https://i.imgur.com/ZF6s192.jpg"
alt="'Floralis Generica' لإدواردو كاتالانو: منحوتة زهرة معدنية عملاقة بتلات عاكسة للضوء"
/>
);
}import Gallery from './Gallery.js';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'))
root.render(<Gallery />);img { margin: 0 10px 10px 0; }- أثناء التصيير الأولي ستقوم React بإنشاء عناصر DOM لعلامات
<section>،<h1>، وثلاث علامات<img>. - أثناء التصيير اللاحق سيحسب الخصائص التي تغيرت منذ التصيير السابق، إن وجدت. لن يفعل أي شيء بهذه المعلومات حتى الخطوة التالية، وهي مرحلة التأكيد.
دائمًا يجب أن يكون التصيير محسوبًا بدقة:
- إن كان نفس المدخلات يجب أن يحصل على نفس الناتج. بالنظر إلى نفس الطلبات، يجب أن يعيد المكون نفس JSX دائمًا. (عندما يطلب شخص ما سلطة مع الطماطم، فلا ينبغي أن يتلقى سلطة مع البصل!)
- يهتم فقط بما يخصه. لا ينبغي أن يغير أي كائنات أو متغيرات كانت موجودة قبل التصيير. (لا ينبغي أن يؤثر طلب واحد على طلبات الآخرين.)
وإلا، يمكنك أن تواجه أخطاءً محيّرة وسلوكًا غير متوقع مع تعقيد بيئة الكود. عند التطوير في "وضع صارم (Srrict Mode)"، ينشئ React كل وظيفة مكون مرتين، مما يساعد على كشف الأخطاء الناتجة عن الوظائف غير النقية.
التصرف الافتراضي لتصيير كل المكونات المتفرعة عن المكون الذي تم تحديثة ليس مثاليًا للأداء إذا كان المكون المحدث عاليًا جدًا في شجرة المكونات. إذا واجهتك مشكلة في الأداء، فهناك طرق مختلفة لحلها، مشروحة في قسم الأداء. لا تستعجل محاولة تحسين الأداء!
بعد تصيير (استدعاء) للمكونات، سيعدل React الـ DOM.
- أثناء التصيير المبدئي سيستخدمReact DOM API
appendChild()لوضع جميع عناصر DOM التي أنشأها على الشاشة. - أثناء إعادة التصيير سينفذ React العمليات اللازمة (التي تم حسابها أثناء التصيير!) لجعل DOM يتطابق مع أحدث نتيجة تصيير.
يغيّر React عناصر DOM فقط إذا كان هناك فرق بين التصييرين. على سبيل المثال، هناك مكون يقوم بإعادة التصيير مع اختلاف الخصائص المُمَرَّرة من المكون الأصلي كل ثانية. لاحظ كيف يمكنك إضافة بعض النص إلى <input>، وتحديث value، ولكن النص لا يختفي عند إعادة تصيير المكون:
export default function Clock({ time }) {
return (
<>
<h1>{time}</h1>
<input />
</>
);
}import { useState, useEffect } from 'react';
import Clock from './Clock.js';
function useTime() {
const [time, setTime] = useState(() => new Date());
useEffect(() => {
const id = setInterval(() => {
setTime(new Date());
}, 1000);
return () => clearInterval(id);
}, []);
return time;
}
export default function App() {
const time = useTime();
return (
<Clock time={time.toLocaleTimeString()} />
);
}هذا يعمل لأنه أثناء هذه الخطوة الأخيرة، يحدّث React محتوى <h1> بالوقت الجديد. يرى React أن <input> يظهر في JSX في نفس المكان كالمرة السابقة، لذلك لا يلمس React الـ <input> - أو value!
بعد الانتهاء من التصيير وتحديث React لـ DOM، سيعيد المتصفح رسم الشاشة. على الرغم من أن هذه العملية معروفة باسم "تصيير المتصفح"، سنشير إليها باسم "رسم" طوال التوثيق لتجنب الخلط.
- يحدث أي تحديث على الشاشة في تطبيق React في ثلاث خطوات:
- التنشيط
- التصيير
- التأكيد
- يمكنك استخدام الوضع الصارم للعثور على الأخطاء في مكوناتك
- لا يلمس React الـ DOM إذا كانت نتيجة التصيير هي نفسها كالمرة السابقة