نظّم الحالة المعقدة بمُخفّض نقي يجمع الانتقالات في مكان واحد ويستبعد التركيبات المستحيلة.
افتح هذا الدرس في Kodokonبمجرد أن يُنسّق مكوّن عدة قيم حالة تتطور معًا - حالة طلب، وبعض البيانات، وخطأ - فإن تكثير استدعاءات useState يبعثر منطق الانتقال عبر كل معالج حدث. تعرف العَرَض: ثلاثة setters يجب استدعاؤها بالترتيب الصحيح، وعاجلاً أم آجلاً تظهر حالة غير متسقة، مثل حالة success بجانب خطأ غير فارغ. يقلب useReducer المسؤولية: تصبح الحالة كائنًا واحدًا، ويمرّ كل تغيير عبر action تفسّره دالة مركزية واحدة، وهي المُخفّض.
function requestReducer(state, action) {
switch (action.type) {
case "start":
return { status: "loading", data: null, error: null };
case "resolve":
return {
status: "success",
data: action.data,
error: null,
};
case "reject":
return {
status: "error",
data: null,
error: action.error,
};
default:
throw new Error("Unknown action: " + action.type);
}
}المُخفّض دالة نقية: يتلقّى الحالة الحالية و action، ثم يُرجع الحالة التالية، دون أي آثار جانبية. الفوائد فورية: الانتقالات صريحة وشاملة، والحالات المستحيلة تختفي من المنبع (كل case يعيد بناء كائن متسق)، ويُقرأ المنطق في مكان واحد بدلاً من تبعثره في كل مكان. علامة تحذير مفيدة: إذا وجدت نفسك تنسخ وتلصق نفس تسلسل استدعاءات setState في مكانين، فأنت على الأرجح تفتقر إلى مُخفّض.
function UserProfile() {
const [state, dispatch] = useReducer(requestReducer, {
status: "idle",
data: null,
error: null,
});
async function load(id) {
dispatch({ type: "start" });
try {
const res = await fetch("/api/users/" + id);
const data = await res.json();
dispatch({ type: "resolve", data });
} catch (error) {
dispatch({ type: "reject", error });
}
}
return <button onClick={() => load(1)}>Load</button>;
}الاختيار بين useState و useReducer ليس مسألة ذوق. احتفظ بـ useState للقيم البسيطة المستقلة؛ وانتقل إلى useReducer عندما تعتمد الحالة التالية على السابقة أو عندما تتغير عدة حقول معًا. ميزتان إضافيتان: المُعامل الثالث يوفّر تهيئة كسولة (useReducer(reducer, arg, init) لا يُشغّل init إلا في أول تصيير)، وتضمن React أن dispatch يحتفظ بنفس الهوية من تصيير إلى آخر - يمكنك تمريره إلى الأبناء دون useCallback.