اللايك لو مستني السيرفر، الزرار يبان متأخر. التحديث المتفائل يغيّر الشاشة الأول، والطلب يمشي وراها.
optimistic-student.jsx
const mutation = useMutation({ mutationFn: updateStudent, onMutate: async (newStudent) => { await queryClient.cancelQueries({ queryKey: ["student", newStudent.id] }); const previous = queryClient.getQueryData(["student", newStudent.id]); queryClient.setQueryData(["student", newStudent.id], newStudent); return { previous }; }, onError: (err, newStudent, context) => { queryClient.setQueryData(["student", newStudent.id], context.previous); }, onSettled: (newStudent) => { queryClient.invalidateQueries({ queryKey: ["student", newStudent.id] }); },});الترتيب:
- onMutate يوقف الطلبات اللي لسه بتجيب نفس الطالب، عشان رد قديم ما يمسحش الكتابة الجديدة.
- تاخد نسخة القديم من getQueryData.
- setQueryData يحط الشكل الجديد في الكاش فورًا.
- ترجع القديم في السياق، عشان لو حصل تراجع.
- onError يرجّع النسخة دي.
- onSettled يبطل المفتاح بعد النجاح أو الفشل، والسيرفر يبقى مصدر الحقيقة.
خلّصت الفصل لما
🧠 اختبر نفسك
١) ليه بنلغي الاستعلامات قبل setQueryData؟
عشان رد جلب قديم ما يستبدلش القيمة اللي المستخدم شافها فورًا.
٢) الطلب فشل. الشاشة ترجع إزاي؟
onError يحط context.previous مكان القيمة المتفائلة.
٣) onSettled ليه موجود حتى بعد النجاح؟
عشان الكاش يتظبط على رد السيرفر، مش على التخمين بس.