البداية · فصل ٢

التحديث من غير ما تبوّظ الحالة

set · replace · immutable · Map · Set
🎯 الهدف: تفرّق الدمج السطحي عن الاستبدال، وتحدّث كائن ومصفوفة و Map من غير تعديل في المكان.

set افتراضيًا بيعمل دمج سطحي. المفاتيح اللي في الكائن الجديد تتبدل، والباقي يفضل.

merge.js
const useCart = create((set, get) => ({  items: [],  note: "",  add: (item) => set({ items: [...get().items, item] }),  setNote: (note) => set({ note }),}));

get يقرا الحالة الحالية جوه الأكشن. شكل الدالة اللي بتاخد الحالة القديمة أأمن لو التحديث مبني عليها، لأن القراءة تبقى لحظة الكتابة. من React 18، كذا تحديث في نفس الحدث بيتجمع في رسم واحد. لو المشروع لسه على React 17، التجميع جوه الوعود كان مختلف، فراجع الدوكس.

الاستبدال الكامل

المعامل التاني true يعني استبدال، مش دمج. الحالة كلها تبقى القيمة الجديدة. لو الحالة رقم أو مصفوفة من بره، الدمج السطحي مش منطقي، فالاستبدال هو الطريق.

replace.js
const useScore = create(() => 0);function bump(next) {  useScore.setState(next, true);}

على كائن فيه أكشنات، الاستبدال بكائن ناقص يمسح الباقي. سيبه للحالة اللي شكلها قيمة واحدة، أو لما بترجّع الحالة الابتدائية كاملة.

الكائن والمصفوفة

التعديل في المكان مش بيتعمل له إشعار. السطر اللي يغيّر الاسم على الكائن القديم يخلّي الشاشة واقفة. السطر الأخضر اتضاف، والأحمر اتشال.

rename.js
function rename(person, name) {  person.name = name;  set({ person: { ...person, name } });}

اعمل كائن جديد. والدمج السطحي يغني عن نسخ كل مفتاح في الجذر، بس الكائن المتداخل محتاج نسخة هو كمان.

nested.js
set((state) => ({  person: { ...state.person, name: "منى" },}));set((state) => ({  items: state.items.filter((item) => item.id !== id),}));

المصفوفة تتبنى بـ map و filter و slice و concat والنسخ الحديثة زي toSorted. push و splice و sort بيعدّلوا المصفوفة القديمة.

Map و Set

الاتنين كمان بيتعدلوا في المكان. انسخهم الأول، وبعدين غيّر النسخة.

map-set.js
addGrade: (id, grade) =>  set((state) => {    const grades = new Map(state.grades);    grades.set(id, grade);    return { grades };  }),toggle: (id) =>  set((state) => {    const picked = new Set(state.picked);    picked.has(id) ? picked.delete(id) : picked.add(id);    return { picked };  }),

خلّصت الفصل لما

🧠 اختبر نفسك
١) set مع note بس. items تروح؟
لأ. الدمج يغيّر note ويفضل items.
٢) غيّرت person.name على نفس الكائن. الشاشة اتحدثت؟
لأ. لازم كائن person جديد يتبعت لـ set.
٣) ليه Map جديد مش grades.set على القديم؟
التعديل في المكان مش إشعار. النسخة الجديدة هي اللي المتجر يشوفها.