React / المكونات والحالة / الدرس 4
الحالة غير المعدلة والقيم المشتقة
حدث الكائنات والمصفوفات دون تعديل اللقطات السابقة وتجنب تخزين ما يمكن اشتقاقه.
في هذه الصفحة
أهداف الدرس
- الحالة الماضية للقراءة
- استبدال الكائن المتغير
- اختبار الانتقالات سلوك مجال
الحالة الماضية للقراءة
قد تكون الحالة كائنا لكن تعديل خاصيته لا ينشئ قيمة جديدة. تعتمد مسارات مهمة الهوية وقد تحتفظ عروض أو إغلاقات بالكائن. يضر التعديل اكتشاف التغيير واللقطات. أنشئ بديلا للسجل واحفظ غير المتغير، ولا تنسخ التطبيق عميقا لكل ضغطة. انسخ مسار الملكية المتغير وبسط البنية.
عمليات بملكية صريحة
ينسخ الانتشار سطحيا فتظل الكائنات الداخلية مشتركة. تنشئ map وfilter والانتشار بدائل، بينما تعدل push وsort وreverse الأصل. لا تكفي مصفوفة خارجية جديدة إذا عُدل عنصرها. طابق المعرف الثابت وأعد كائنا جديدا له وحده. تمنع الملكية الواضحة تغيير بيانات لقطة أخرى.
استبدال الكائن المتغير
يزيد المثال نتيجة داخلية بنسخ الملف وإحصاءاته معا، ويحتفظ بالاسم. كان النسخ الخارجي ثم next.stats.score++ سيعدل الأصل. اختبر اللقطة السابقة عند كتابة دالة انتقال. يجب ألا يتغير الناتج بتكرار الحساب لأنه لا يعدل كائنا سابقا.
import { useState } from "react";
export default function App() { const [profile, setProfile] = useState({ name: "Mira", stats: { score: 2 } }); return <main><h1>{profile.name}</h1><p>{profile.stats.score}</p><button type="button" onClick={() => setProfile(p => ({ ...p, stats: { ...p.stats, score: p.stats.score + 1 } }))}>Add point</button></main>; }
Mira. Initial score: 2. After Add point: 3.
يستبدل مستويا المسار فتزداد النتيجة من اثنين لثلاثة ويبقى الاسم.
اشتقاق المعلومات أثناء العرض
يخزن المثال السجلات ويشتق المجموع. تخزين الاثنين يلزم كل تعديل وحذف وضبط بصيانة اتساقهما. يتجنب الحساب النقي الرخيص الازدواج، وينطبق ذلك على التصفية والسجل المحدد بالمعرف والتسميات. قد تخزن memo حسابا مكلفا لاحقا لكنها لا تبرر ازدواج الحالة ولا تصلح عدم النقاء. حدد مصدر الحقيقة وثابته أولا.
import { useState } from "react";
export default function App() { const [items, setItems] = useState([{ id: "a", amount: 2 }, { id: "b", amount: 3 }]); const total = items.reduce((sum, item) => sum + item.amount, 0); return <main><h1>Total: {total}</h1><button type="button" onClick={() => setItems(xs => xs.filter(x => x.id !== "a"))}>Remove A</button></main>; }
Initial: Total: 5. After Remove A: Total: 3.
يشتق المجموع من المصفوفة ويصبح ثلاثة بعد الحذف دون محدث مجموع آخر.
اختبار الانتقالات سلوك مجال
افحص الجديد وغير المرتبط وحفظ المدخل، واختبر معرفا غائبا والفراغ والتكرار. لا تشترط هوية جديدة لكل داخلية؛ يجوز حفظ غير المتغير. ولا تثبت الهوية الجديدة صحة المجال، فقد ينقص المخزون بسلبية رغم الثبات. يدعم الثبات التوقع وتبقى قيود المجال مستقلة ظاهرة.
الأخطاء الشائعة وإصلاحها
يتغير الكائن دون تحديث موثوق
- لماذا يحدث؟
- عُدلت الحالة وأعيدت هويتها.
- كيف تصلحه؟
- أنشئ بديلا للمسار.
- كيف تتجنب تكراره؟
- اعتبر السابق مدخلا ثابتا.
تتغير داخلية قديمة
- لماذا يحدث؟
- نسخ الانتشار الخارج فقط.
- كيف تصلحه؟
- استبدل الداخلية المتغيرة.
- كيف تتجنب تكراره؟
- اختبر حفظ الأصل.
ينفصل المجموع عن القائمة
- لماذا يحدث؟
- لم تحدث الحالة المكررة بكل مسار.
- كيف تصلحه؟
- اشتق المجموع من القائمة.
- كيف تتجنب تكراره؟
- خزن المستقل فقط.
اختبر فهمك
1. صف تحديثا ثابتا يكمل مهمة بمعرفها.
اعرض الحل المشروح
استخدم map وأعد كائنا جديدا بـcomplete: true للمطابق، وأبق الباقي وأعد المصفوفة. يحفظ ذلك اللقطات وهويات المهام الأخرى.
2. هل يخزن المكون الكائن المحدد ومعرفه مستقلين؟
اعرض الحل المشروح
خزن المعرف عادة واشتق الكائن، وإلا قد يبقى كائن قديم بعد استبداله أو حذفه. حدد الغياب صراحة كإلغاء الاختيار.
أهم ما تعلمته
- انسخ المسار المتغير لا كل شيء عشوائيا.
- يتجنب الاشتقاق عيوب المزامنة.
- الثبات وصحة المجال منفصلان.