متى نهتمّ بالأداء؟
React سريع افتراضيًا. لكن في التطبيقات الكبيرة، قد تُعاد عمليات عرض كثيرة بلا داعٍ. هذه الأدوات تساعد — لكن لا تُفرط فيها؛ استخدمها عند وجود مشكلة فعلية.
React.memo — منع إعادة عرض مكوّن
يمنع إعادة عرض المكوّن إن لم تتغيّر خصائصه (props):
import { memo } from "react";
const UserCard = memo(function UserCard({ name }) {
console.log("عرض UserCard");
return <div>{name}</div>;
});
الآن UserCard لا يُعاد عرضه إلا إذا تغيّرت name.
useMemo — تذكّر قيمة محسوبة
يحفظ نتيجة حساب ثقيل ولا يعيد حسابه إلا عند تغيّر اعتمادياته:
const expensiveResult = useMemo(() => {
return heavyCalculation(items);
}, [items]); // يُعاد الحساب فقط عند تغيّر items
useCallback — تذكّر دالة
يحفظ نفس مرجع الدالة بين العروض. مفيد عند تمرير دوال لمكوّنات memo:
const handleClick = useCallback(() => {
console.log(id);
}, [id]); // نفس الدالة ما لم يتغيّر id
مثال: لماذا نحتاجها معًا
function Parent() {
const [count, setCount] = useState(0);
// بدون useCallback، تُنشأ دالة جديدة كل عرض،
// فيُعاد عرض Child (memo) بلا داعٍ
const handleClick = useCallback(() => {
console.log("نقر");
}, []);
return (
<>
<button onClick={() => setCount(count + 1)}>{count}</button>
<Child onClick={handleClick} />
</>
);
}
const Child = memo(function Child({ onClick }) {
return <button onClick={onClick}>طفل</button>;
});
أدوات أخرى للأداء
- القوائم الطويلة: استخدم مفاتيح
keyثابتة، وفكّر في "التمرير الافتراضي" (virtualization). - تقسيم الكود:
React.lazyوSuspenseلتحميل المكوّنات عند الحاجة.
⚠️ لا تُحسّن مبكّرًا
🔑 التحسين المبكّر شرّ. لا تلفّ كل شيء بـ
memo/useMemo. قِس أولًا (React DevTools Profiler)، وحسّن ما يحتاج فعلًا.
الأخطاء الشائعة
- ❌ الإفراط في
useMemo/useCallback→ تعقيد بلا فائدة (لها تكلفة أيضًا). - ❌
memoمع props تتغيّر دائمًا (مثل دالة جديدة كل عرض) → بلا فائدة. - ❌ التحسين قبل قياس مشكلة حقيقية.
خلاصة
memo يمنع إعادة عرض مكوّن، useMemo يحفظ قيمة محسوبة، useCallback يحفظ دالة. استخدمها معًا عند الحاجة الفعلية فقط — قِس أولًا بـ Profiler ثم حسّن. تجنّب التحسين المبكّر.