في هذا الدرس 6تصفّح المواضيع
يمر كل تحديث يظهر على شاشة تطبيق React عبر خط أنابيب هندسي واضح من ثلاث مراحل متتابعة:
- تحفيز التصيير (Trigger): ينطلق إما عند التركيب الأولي للتطبيق عبر
createRootأو عند استدعاء دالة تحديث حالة مثلsetSeats(). - تصيير المكون (Render): تستدعي React دالة المكون النقية لحساب شجرة
JSXالجديدة. - الاعتماد في المتصفح (Commit): تطبّق React الفروق الفعلية فقط على عقد
DOMالمتغيرة دون المساس بالعناصر الثابتة.
import { useState } from 'react';
function OrderTicket() {
const [n, setN] = useState(1);
return (
<div className="rx-card">
<p>Tickets Requested: {n}</p>
<input placeholder="Type note (preserved!)" />
<button onClick={() => setN(n + 1)}>+1</button>
</div>
);
}
تتصرف الحالة في React مثل لقطة فوتوغرافية ثابتة (Snapshot) خاصة بكل عملية تصيير؛ فاستدعاء setCount(count + 1) لا يغيّر قيمة المتغير count داخل دالة الحدث الجارية حالياً، بل تظل قيمته ثابتة حتى تنتهي الدالة، وتجدول React تصييراً جديداً يحمل لقطة محدثة بالقيمة الجديدة.
import { useState } from 'react';
function SnapshotTrap() {
const [score, setScore] = useState(0);
function bump() {
setScore(score + 1);
setScore(score + 1);
}
return <button onClick={bump}>Pts: {score}</button>;
}
يفسر نموذج اللقطة الثابتة أيضاً سلوك المؤقتات والدوال غير المتزامنة مثل setTimeout()؛ فالدالة المجدولة تقرأ قيمة الحالة التي التُقطت في التصيير الذي أنشأ ذلك الحدث، حتى لو نقر المستخدم لاحقاً وولّد تصييرات أحدث بقيم مختلفة.
ماذا يحدث عندما تستدعي دالة نقر واحدة ثلاث دوال تحديث منفصلة متتالية؟ تنتظر React حتى ينتهي تنفيذ جميع أسطر معالج الحدث بالكامل ثم تجري إعادة تصيير مجمعة واحدة فقط، وتُعرف هذه الميزة باسم التجميع التلقائي (Automatic Batching) لمنع الرسوم الجزئية المهدرة للأداء.
عندما تحتاج فعلياً لتحديث متغير الحالة نفسه عدة مرات متتالية في حدث واحد أو الاعتماد المضمون على آخر قيمة مجدولة، مرّر دالة تحديث نقية (Updater Function) بصيغة setCount(c => c + 1)؛ إذ تضعها React في طابور مرتب وتمرر ناتج كل دالة كمدخل للدالة التي تليها.
import { useState } from 'react';
function ComboCounter() {
const [pts, setPts] = useState(0);
function addThree() {
setPts((p) => p + 1);
setPts((p) => p + 1);
setPts((p) => p + 1);
}
return <button onClick={addThree}>XP: {pts}</button>;
}
أخيراً، إذا كانت القيمة الأولية للحالة تتطلب حساباً مكلفاً مثل توليد مصفوفة مقاعد كبيرة أو تحليل نص مخزن، فتجنب كتابة useState(buildMatrix()) لأن الأقواس ستشغل الدالة هدراً في كل إعادة تصيير! بدلاً من ذلك مرّر دالة تهيئة كسولة (Lazy Initializer) بصيغة useState(() => buildMatrix()) لتنفذها React مرة واحدة فقط عند التركيب الأول. قارن الآليات في الجدول التالي:
| صيغة الاستدعاء | المثال البرمجي | السلوك الدقيق وقت التشغيل |
|---|---|---|
| استبدال بقيمة اللقطة | setCount(count + 1) | يعتمد على قيمة اللقطة الثابتة للتصيير الحالي |
| دالة التحديث المتسلسلة | setCount(c => c + 1) | تقرأ أحدث قيمة في الطابور وتدعم التحديثات المتتالية |
| تهيئة مبكرة مهدرة | useState(heavyCalc()) | تُشغّل الدالة المكلفة في كل إعادة رسم دون حاجة |
| تهيئة كسولة عالية الكفاءة | useState(() => heavyCalc()) | تُشغّل دالة الحساب مرة وحيدة عند التركيب الأول |
import { useState } from 'react';
function createInitialSeats() {
return ['A1', 'A2', 'B1', 'B2'];
}
function SeatHall() {
const [seats] = useState(createInitialSeats);
return <p>Loaded {seats.length} seats once.</p>;
}
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
تتبعت في هذا الدرس دورة التحفيز والتصيير والاعتماد، وفهمت ثبات لقطة الحالة داخل المعالجات والمؤقتات، واستفدت من التجميع التلقائي للتحديثات وطوابير دوال التحديث والتهيئة الكسولة عالية الكفاءة. الخطوة التالية: انتقل الآن إلى الدرس رقم 20 «تحديث الكائنات في الحالة دون تعديل مباشر» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 State Snapshot لقطة الحالة
- القيمة الثابتة لمتغير الحالة خلال دورة تصيير واحدة والتي تقرأها جميع الدوال المنشأة في تلك اللقطة.
- للمراجعة
- 02 Commit Phase مرحلة الاعتماد
- المرحلة الثالثة بعد التصيير والتي تطبق فيها React الفروق المحسوبة الفعلية على شجرة المتصفح.
- للمراجعة
- 03 Automatic Batching التجميع التلقائي للتحديثات
- دمج React لعدة استدعاءات تحديث حالة متتالية في عملية إعادة تصيير واحدة عالية الكفاءة.
- للمراجعة
- 04 Lazy Initializer دالة التهيئة الكسولة
- دالة بدون معاملات تُمرر إلى useState لتشغيل الحساب الابتدائي المكلف مرة واحدة فقط عند التركيب.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 DOM DOM
- Document Object Model
- شجرة عناصر المتصفح الحية التي تُحدّث انتقائياً بأقل تكلفة خلال مرحلة الاعتماد.
- للمراجعة
- 02 FIFO FIFO
- First In, First Out
- نظام الطابور المتسلسل الذي تعالج به React دوال التحديث المجدولة بالترتيب عند التصيير التالي.
- للمراجعة
- 03 UI UI
- User Interface
- المخرجات البصرية المحسوبة بوصفها دالة نقية للقطة الحالة الحالية.
- للمراجعة
- 04 JS JS
- JavaScript
- قواعد الإغلاق اللفظي في اللغة التي تفسر احتفاظ المؤقتات بقيمة اللقطة التي أنشأتها.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
افتح مثال عداد النقاط في محرر التجريب وأضف زراً يجدول دالتي تحديث بمجموع 5 نقاط وتحقق من دقة النتيجة.
-
افتح مثال التهيئة الكسولة في محرر التجريب وانقر زر إعادة التصيير خمس مرات للتأكد من بقاء عدد استدعاءات التهيئة عند 1.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي10 أسئلة تنتظرك +
إذا كانت قيمة count تساوي 0 في التصيير الحالي واستدعت دالة النقر setCount(count + 1) ثلاث مرات متتالية، فكم ستصبح قيمة count؟
تظل count تساوي 0 طوال اللقطة الحالية، لذا تطلب الاستدعاءات الثلاثة ضبط القيمة على 1 فتصبح النتيجة 1.
أي صياغة برمجية تضمن زيادة المتغير count ثلاث مرات متتالية داخل نفس دالة الحدث؟
تمرير دالة التحديث setCount(c => c + 1) ثلاث مرات يضعها في طابور متسلسل يعتمد آخر قيمة.
ما المراحل الثلاث المتتابعة لتحديث واجهة الشاشة في مكتبة React؟
تبدأ بتحفيز التحديث، ثم تصيير دالة المكون، وأخيراً اعتماد التغييرات في شجرة DOM.
في الإصدار الثامن عشر من React، تُجمع عدة تحديثات للحالة داخل دالة نقر واحدة في عملية إعادة تصيير واحدة تلقائياً.
صواب؛ إذ يمنع التجميع التلقائي عمليات الرسم الجزئية المتكررة ويحسن الأداء.
كيف تمرر دالة التهيئة المكلفة buildInitialBoard إلى useState بحيث تعمل مرة واحدة فقط عند التركيب الأول؟
نمرر مرجع الدالة useState(buildInitialBoard) أو دالة سهمية بدون استدعاء فوري بالأقواس.
تقرأ دالة setTimeout المنشأة داخل معالج النقر قيمة لقطة الحالة التي كانت موجودة لحظة النقر حتى لو حدثت تصييرات أحدث بعدها.
صواب؛ لأن كل دورة تصيير تحتفظ بنطاق إغلاق مستقل لقيم الحالة الخاصة بها.
خلال مرحلة الاعتماد Commit، تهدم React جميع عناصر DOM المجاورة غير المتغيرة وتعيد بناءها من الصفر.
خطأ؛ إذ تعدّل React العقد والسمات التي تغيرت فعلياً فقط وتحافظ على بقية العناصر كما هي.
يجب أن تكون دوال التحديث الممررة إلى setState(prev => next) دوال نقية خالية من التأثيرات الجانبية.
صواب؛ لأنها تعمل أثناء مرحلة التصيير وتختبرها React مرتين في وضع StrictMode للتأكد من نقائها.
إذا بدأت count بالقيمة 5 ونفذ المعالج setCount(count + 2) متبوعاً بـ setCount(c => c * 2)، فكم تصبح النتيجة النهائية؟
تضبط الخطوة الأولى القيمة في الطابور على 7، ثم تستلم دالة التحديث القيمة 7 وتضربها في 2 لتصبح 14.
ما العيب الأدائي في كتابة useState(parseHugeData()) بأقواس الاستدعاء المباشر؟
تُنفذ الدالة الثقيلة في كل إعادة تصيير للمكون رغم أن React تتجاهل ناتجها بعد التصيير الأول.