العربية

أطلق العنان لقوة نمط React Render Props. تعلم كيف يعزز إعادة استخدام التعليمات البرمجية، وتركيب المكونات، وفصل الاهتمامات، مما يتيح تطبيقات مرنة وقابلة للصيانة للجمهور العالمي.

نمط React Render Props: منطق مكون مرن لجمهور عالمي

في المشهد المتطور باستمرار لتطوير الواجهة الأمامية، وخاصة داخل نظام React البيئي، تلعب الأنماط المعمارية دورًا حاسمًا في بناء مكونات قابلة للتطوير والصيانة وإعادة الاستخدام. من بين هذه الأنماط، يبرز نمط Render Props كتقنية قوية لمشاركة التعليمات البرمجية والمنطق بين مكونات React. تهدف هذه المقالة إلى توفير فهم شامل لنمط Render Props وفوائده وحالات استخدامه وكيف يساهم في بناء تطبيقات قوية وقابلة للتكيف لجمهور عالمي.

ما هي Render Props؟

Render Prop هي تقنية بسيطة لمشاركة التعليمات البرمجية بين مكونات React باستخدام خاصية قيمتها دالة. في الأساس، يأخذ المكون المزود بـ render prop دالة تُرجع عنصر React ويستدعي هذه الدالة لعرض شيء ما. لا يقرر المكون ما يجب عرضه مباشرة؛ بل يفوض هذا القرار إلى دالة render prop، ويزودها بإمكانية الوصول إلى حالته ومنطقه الداخلي.

ضع في اعتبارك هذا المثال الأساسي:


class DataProvider extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null };
  }

  componentDidMount() {
    // Simulate fetching data
    setTimeout(() => {
      this.setState({ data: 'Some data from an API' });
    }, 1000);
  }

  render() {
    return this.props.render(this.state.data);
  }
}

function MyComponent() {
  return (
     (
        
{data ?

Data: {data}

:

Loading...

}
)} /> ); }

في هذا المثال، يجلب DataProvider البيانات ويمررها إلى دالة الخاصية render التي يوفرها MyComponent. ثم يستخدم MyComponent هذه البيانات لعرض محتواه.

لماذا نستخدم Render Props؟

يوفر نمط Render Props العديد من المزايا الرئيسية:

حالات الاستخدام الواقعية والأمثلة الدولية

نمط Render Props ذو قيمة في مجموعة متنوعة من السيناريوهات. فيما يلي بعض حالات الاستخدام الشائعة مع أمثلة تراعي جمهورًا عالميًا:

1. تتبع الماوس

تخيل أنك تريد تتبع موضع الماوس على صفحة ويب. باستخدام Render Prop، يمكنك إنشاء مكون MouseTracker يوفر إحداثيات الماوس لأبنائه.


class MouseTracker extends React.Component {
  constructor(props) {
    super(props);
    this.state = { x: 0, y: 0 };
  }

  handleMouseMove = event => {
    this.setState({ x: event.clientX, y: event.clientY });
  };

  render() {
    return (
      
{this.props.render(this.state)}
); } } function MyComponent() { return ( (

The mouse position is ({x}, {y})

)} /> ); }

يمكن تكييف هذا بسهولة للتطبيقات المدعومة دوليًا. على سبيل المثال، تخيل تطبيق رسم يستخدمه فنانون في اليابان. يمكن استخدام إحداثيات الماوس للتحكم في ضربات الفرشاة:


 (
    
  )}
/>

2. جلب البيانات من واجهات برمجة التطبيقات

يعد جلب البيانات من واجهات برمجة التطبيقات مهمة شائعة في تطوير الويب. يمكن لمكون Render Prop التعامل مع منطق جلب البيانات وتوفير البيانات لأبنائه.


class APIFetcher extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: null, loading: true, error: null };
  }

  async componentDidMount() {
    try {
      const response = await fetch(this.props.url);
      const data = await response.json();
      this.setState({ data: data, loading: false });
    } catch (error) {
      this.setState({ error: error, loading: false });
    }
  }

  render() {
    return this.props.render(this.state);
  }
}

function MyComponent() {
  return (
     {
        if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; return
{JSON.stringify(data, null, 2)}
; }} /> ); }

هذا مفيد بشكل خاص عند التعامل مع البيانات المترجمة. على سبيل المثال، تخيل عرض أسعار صرف العملات للمستخدمين في مناطق مختلفة:


 {
    if (loading) return 

Loading exchange rates...

; if (error) return

Error fetching exchange rates.

; return (
    {Object.entries(data.rates).map(([currency, rate]) => (
  • {currency}: {rate}
  • ))}
); }} />

3. معالجة النماذج

يمكن أن يكون لإدارة حالة النموذج والتحقق من صحته أمرًا معقدًا. يمكن لمكون Render Prop تغليف منطق النموذج وتوفير حالة النموذج ومعالجاته لأبنائه.


class FormHandler extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '', error: null };
  }

  handleChange = event => {
    this.setState({ value: event.target.value });
  };

  handleSubmit = event => {
    event.preventDefault();
    if (this.state.value.length < 5) {
      this.setState({ error: 'Value must be at least 5 characters long.' });
      return;
    }
    this.setState({ error: null });
    this.props.onSubmit(this.state.value);
  };

  render() {
    return this.props.render({
      value: this.state.value,
      handleChange: this.handleChange,
      handleSubmit: this.handleSubmit,
      error: this.state.error
    });
  }
}

function MyComponent() {
  return (
     alert(`Submitted value: ${value}`)}
      render={({ value, handleChange, handleSubmit, error }) => (
        
{error &&

{error}

}
)} /> ); }

ضع في اعتبارك تكييف قواعد التحقق من صحة النموذج لتلبية تنسيقات العناوين الدولية. يمكن أن يظل مكون `FormHandler` عامًا، بينما يحدد render prop منطق التحقق من الصحة وواجهة المستخدم المحددة لمناطق مختلفة:


 sendAddressToServer(address)}
  render={({ value, handleChange, handleSubmit, error }) => (
    
{/* Fields for address, adapting to regional formats */} {error &&

{error}

}
)} />

4. علامات الميزات واختبار A/B

يمكن أيضًا استخدام Render Props لإدارة علامات الميزات وإجراء اختبارات A/B. يمكن لمكون Render Prop تحديد إصدار الميزة المراد عرضه بناءً على المستخدم الحالي أو علامة تم إنشاؤها عشوائيًا.


class FeatureFlag extends React.Component {
  constructor(props) {
    super(props);
    this.state = { enabled: Math.random() < this.props.probability };
  }

  render() {
    return this.props.render(this.state.enabled);
  }
}

function MyComponent() {
  return (
     {
        if (enabled) {
          return 

New Feature!

; } else { return

Old Feature

; } }} /> ); }

عند إجراء اختبار A/B لجمهور عالمي، من المهم تقسيم المستخدمين بناءً على اللغة أو المنطقة أو البيانات الديموغرافية الأخرى. يمكن تعديل مكون `FeatureFlag` لمراعاة هذه العوامل عند تحديد إصدار الميزة المراد عرضه:


 {
    return isEnabled ?  : ;
  }}
/>

بدائل لـ Render Props: المكونات ذات الترتيب الأعلى (HOCs) والخطافات

في حين أن Render Props هو نمط قوي، إلا أن هناك طرقًا بديلة يمكن أن تحقق نتائج مماثلة. البديلان الشائعان هما المكونات ذات الترتيب الأعلى (HOCs) والخطافات.

المكونات ذات الترتيب الأعلى (HOCs)

المكون ذو الترتيب الأعلى (HOC) هو دالة تأخذ مكونًا كمعامل وتُرجع مكونًا جديدًا ومحسنًا. تُستخدم HOCs بشكل شائع لإضافة وظائف أو منطق إلى المكونات الحالية.

على سبيل المثال، يمكن لـ HOC `withMouse` توفير وظيفة تتبع الماوس للمكون:


function withMouse(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = { x: 0, y: 0 };
    }

    handleMouseMove = event => {
      this.setState({ x: event.clientX, y: event.clientY });
    };

    render() {
      return (
        
); } }; } function MyComponent(props) { return (

The mouse position is ({props.mouse.x}, {props.mouse.y})

); } const EnhancedComponent = withMouse(MyComponent);

في حين أن HOCs توفر إعادة استخدام التعليمات البرمجية، إلا أنها يمكن أن تؤدي إلى حدوث تصادمات في أسماء الخصائص وتجعل تركيب المكونات أكثر صعوبة، وهي ظاهرة تُعرف باسم "جحيم الغلاف".

الخطافات

توفر خطافات React، التي تم تقديمها في React 16.8، طريقة أكثر مباشرة وتعبيراً لإعادة استخدام المنطق ذي الحالة بين المكونات. تتيح لك الخطافات "الربط" بميزات حالة دورة حياة React من مكونات الوظائف.

باستخدام الخطاف `useMousePosition`، يمكن تنفيذ وظيفة تتبع الماوس على النحو التالي:


import { useState, useEffect } from 'react';

function useMousePosition() {
  const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    function handleMouseMove(event) {
      setMousePosition({ x: event.clientX, y: event.clientY });
    }

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, []);

  return mousePosition;
}

function MyComponent() {
  const mousePosition = useMousePosition();
  return (
    

The mouse position is ({mousePosition.x}, {mousePosition.y})

); }

توفر الخطافات طريقة أنظف وأكثر إيجازًا لإعادة استخدام المنطق ذي الحالة مقارنة بـ Render Props و HOCs. كما أنها تعزز سهولة قراءة التعليمات البرمجية وصيانتها بشكل أفضل.

Render Props مقابل الخطافات: اختيار الأداة المناسبة

يعتمد تحديد ما بين Render Props والخطافات على المتطلبات المحددة لمشروعك وتفضيلاتك الشخصية. فيما يلي ملخص للاختلافات الرئيسية بينهما:

أفضل الممارسات لاستخدام Render Props

لاستخدام نمط Render Props بفعالية، ضع في اعتبارك أفضل الممارسات التالية:

الخلاصة

نمط Render Props هو أسلوب قيِّم لبناء مكونات React مرنة وقابلة لإعادة الاستخدام. من خلال تغليف المنطق وتوفيره للمكونات من خلال render prop، يمكنك تعزيز إعادة استخدام التعليمات البرمجية وتركيب المكونات وفصل الاهتمامات. في حين أن الخطافات توفر بديلاً أحدث وغالبًا ما يكون أبسط، إلا أن Render Props تظل أداة قوية في ترسانة مطور React، خاصة عند التعامل مع التعليمات البرمجية القديمة أو السيناريوهات التي تتطلب تحكمًا دقيقًا في عملية العرض.

من خلال فهم فوائد وأفضل ممارسات نمط Render Props، يمكنك بناء تطبيقات قوية وقابلة للتكيف تلبي احتياجات جمهور عالمي متنوع، مما يضمن تجربة مستخدم متسقة وجذابة عبر مناطق وثقافات مختلفة. المفتاح هو اختيار النمط الصحيح - Render Props أو HOCs أو الخطافات - بناءً على الاحتياجات المحددة لمشروعك وخبرة فريقك. تذكر دائمًا إعطاء الأولوية لسهولة قراءة التعليمات البرمجية وصيانتها وأدائها عند اتخاذ قرارات معمارية.