0Pricing
Frontend Academy · درس

أنماط Render Props وHOC

مرّر دالة render باعتبارها prop لحقن واجهة المستخدم، وغلّف المكوّنات داخل Higher-Order Components لحقن السلوك دون تعديل المكوّن الأصلي

أنماط Render Props وHOC درس مجاني في Frontend Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Frontend Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Frontend Academy 4 دروس في المجموع.

نمطان كلاسيكيان لإعادة الاستخدام

قبل Hooks (في React 16.8)، كانت إعادة استخدام المنطق ذي الحالة تعني استخدام Higher-Order Components (HOCs) أو render props. نادرًا ما تُستخدم هذه الأنماط في الشيفرة الجديدة، لكنك ستصادفها في الشيفرات القديمة وفي العديد من المكتبات.

Render Props — الفكرة

يقبل المكوّن دالةً كخاصية (تُسمى عادةً render أو children) ويستدعيها مع الحالة الداخلية. ويحدد المستهلك ما يجب تصييره باستخدام تلك الحالة.

function Mouse({ render }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handler);
    return () => window.removeEventListener('mousemove', handler);
  }, []);
  return render(pos);
}

// Usage:
<Mouse render={({ x, y }) => <p>{x}, {y}</p>} />

children بوصفها دالة

يمكن أن تكون خاصية children دالةً أيضًا، وهو النمط نفسه مع JSX أنظف.

function Mouse({ children }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  /* ... */
  return children(pos);
}

<Mouse>
  {({ x, y }) => <p>{x}, {y}</p>}
</Mouse>

Higher-Order Components — الفكرة

HOC هي دالة تأخذ مكوّنًا وتعيد مكوّنًا جديدًا بخصائص أو سلوك إضافي. وقد استُخدمت بكثافة في connect() الخاص بـ Redux وwithRouter() الخاص بـ React Router.

function withMouse(Component) {
  return function WithMouse(props) {
    const [pos, setPos] = useState({ x: 0, y: 0 });
    useEffect(() => {
      const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
      window.addEventListener('mousemove', handler);
      return () => window.removeEventListener('mousemove', handler);
    }, []);
    return <Component {...props} mouse={pos} />;
  };
}

// Usage:
const Position = ({ mouse }) => <p>{mouse.x}, {mouse.y}</p>;
const EnhancedPosition = withMouse(Position);
<EnhancedPosition />

تتكوّن HOCs عبر التغليف

يمكنك تكديس HOCs، لكنها تُنشئ «جحيمًا من الأغلفة» يصعب تصحيحه.

// Multiple HOCs:
const Enhanced = withRouter(connect(mapState)(withTranslation()(MyComponent)));
// Equivalent in modern React:
// const Enhanced = MyComponent (reads from hooks: useRouter, useSelector, useTranslation)

Render Props مقارنةً بـ HOC

Render props: أكثر وضوحًا، وأكثر توافقًا مع الأنواع، ولا تتضمن تعارضات في الأسماء. أما HOCs فهي أكثر تصريحية، وقد تفقد الأنواع الثابتة للمكوّنات المغلّفة من دون عناية، كما يمكن أن تحدث تعارضات في أسماء الخصائص.

لماذا استبدلت Hooks كليهما؟

تحقق Hooks المخصّصة الهدف نفسه بقدر أقل من التعقيد: فلا توجد مكوّنات تغليف، ولا معاملات دوال متداخلة، ولا تحايلات على الأنواع. وتُعد Hooks الحل الاصطلاحي في 2025.

// Custom hook equivalent of useMouse:
function useMouse() {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const handler = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handler);
    return () => window.removeEventListener('mousemove', handler);
  }, []);
  return pos;
}

// Usage:
const { x, y } = useMouse();

متى تظل Render Props الخيار الأفضل؟

بالنسبة إلى المكوّنات التي تحتاج إلى حقن بنية HTML (وليس الحالة فقط)، مثل القوائم الافتراضية التي تصيّر العناصر في مواضع محددة، تظل Render Props الخيار الطبيعي.

function VirtualList({ items, itemHeight, renderItem }) {
  const [scrollTop, setScrollTop] = useState(0);
  const start = Math.floor(scrollTop / itemHeight);
  const visible = items.slice(start, start + 20);
  return visible.map((item, i) => renderItem(item, start + i));
}

<VirtualList items={data} itemHeight={40} renderItem={(item, i) => (
  <Row key={i} data={item} />
)} />

أفضل ممارسات HOC (عند الحاجة)

إذا اضطررت إلى كتابة HOC: فانقل الدوال الثابتة (hoist-non-react-statics)، ومرّر المراجع (React.forwardRef)، وحافظ على displayName لأدوات DevTools.

تمرير المراجع في HOCs

تحجب HOCs المراجع افتراضيًا، لذا استخدم forwardRef حتى يتمكن المستهلكون من الوصول إلى مرجع المكوّن الأساسي.

function withLogger(Component) {
  const Wrapped = React.forwardRef((props, ref) => {
    console.log('rendering', Component.name);
    return <Component {...props} ref={ref} />;
  });
  Wrapped.displayName = `withLogger(${Component.name})`;
  return Wrapped;
}

التعرّف على الأنماط القديمة

ستصادف HOCs وrender props في: react-redux (واجهة API القديمة)، وApollo Client v2، وreact-router v5 (withRouter)، وFormik (Field)، وstyled-components (withTheme). أعد البناء باستخدام Hooks عندما تتيح واجهات API الأحدث لهذه المكتبات ذلك.

اختبار سريع

ما النمط الذي استبدلته Hooks إلى حد كبير لمشاركة المنطق ذي الحالة بين مكوّنات React؟

مراجعة: Render Props وHOCs

Render props: دالة بوصفها خاصية تُعيد JSX، وهي واضحة ومتوافقة مع الأنواع. HOCs: دالة تغلّف مكوّنًا، وتستخدمها المكتبات القديمة مثل connect وwithRouter. استبدلت Hooks المخصّصة كليهما في منطق الحالة. تظل Render props الخيار الأفضل عند الحاجة إلى حقن بنية HTML مخصّصة (مثل القوائم الافتراضية). عند كتابة HOCs: استخدم forwardRef، وانقل الخصائص الثابتة، واضبط displayName.

الأسئلة الشائعة

هل درس «أنماط Render Props وHOC» مجاني؟

نعم — نص درس «أنماط Render Props وHOC» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Frontend Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Frontend Academy 4 دروس في المجموع.

ماذا ستتعلم في «أنماط Render Props وHOC»؟

مرّر دالة render باعتبارها prop لحقن واجهة المستخدم، وغلّف المكوّنات داخل Higher-Order Components لحقن السلوك دون تعديل المكوّن الأصلي تتمرن على Frontend Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Frontend Academy؟

لا تُشترط خبرة سابقة. Frontend Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «أنماط Render Props وHOC»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Frontend Academy هذا؟

نعم. كل درس في Frontend Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. المكوّنات المركّبة باستخدام Context
  2. أنماط Render Props وHOC
  3. Portals للنوافذ المنبثقة والتلميحات
  4. حدود الأخطاء
← العودة إلى Frontend Academy