الفرق بين المراجعتين ل"React/react without es6"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(تحديث)
 
(6 مراجعات متوسطة بواسطة 3 مستخدمين غير معروضة)
سطر 11: سطر 11:
 
var Greeting = createReactClass({
 
var Greeting = createReactClass({
 
   render: function() {
 
   render: function() {
     return <h1>أهلًا {this.props.name}</h1>;
+
     return <h1>Hello, {this.props.name}</h1>;
 
   }
 
   }
 
});
 
});
 
 
</syntaxhighlight>تُشبِه واجهة برمجة التطبيقات لأصناف ES6 الصنف <code>createReactClass()‎</code> مع بعض الاستثناءات.
 
</syntaxhighlight>تُشبِه واجهة برمجة التطبيقات لأصناف ES6 الصنف <code>createReactClass()‎</code> مع بعض الاستثناءات.
  
سطر 106: سطر 105:
 
</syntaxhighlight>يعني هذا أن كتابة أصناف ES6 يحتاج لكتابة شيفرة متكررة من أجل معالجات الأحداث ولكنّ الجانب الجيد هنا هو الحصول على أداء أفضل قليلًا في التطبيقات الكبيرة.
 
</syntaxhighlight>يعني هذا أن كتابة أصناف ES6 يحتاج لكتابة شيفرة متكررة من أجل معالجات الأحداث ولكنّ الجانب الجيد هنا هو الحصول على أداء أفضل قليلًا في التطبيقات الكبيرة.
  
إن كنت لا تحب كتابة الشيفرة بشكل متكرر فتستطيع تمكين صياغة خاصيّات الأصناف التجريبية مع Babel:<syntaxhighlight lang="javascript">
+
إن لم تكرار كتابة الشيفرة فتستطيع تمكين صياغة [https://babeljs.io/docs/plugins/transform-class-properties/ خاصيّات الأصناف] التجريبية مع Babel:<syntaxhighlight lang="javascript">
 
class SayHello extends React.Component {
 
class SayHello extends React.Component {
 
   constructor(props) {
 
   constructor(props) {
سطر 132: سطر 131:
 
* ربط التوابع في الدالة البانية.
 
* ربط التوابع في الدالة البانية.
 
* استخدام الدوال السهمية، مثل <code>‎onClick={(e) => this.handleClick(e)}</code>‎.
 
* استخدام الدوال السهمية، مثل <code>‎onClick={(e) => this.handleClick(e)}</code>‎.
* الاستمرار في استخدام createReactClass.
+
* الاستمرار في استخدام <code>createReactClass</code>.
  
 
== المخاليط (Mixins) ==
 
== المخاليط (Mixins) ==
 
المخاليط هي الأصناف التي تحتوي على دوال متاحة من أجل استخدامها من قبل أصناف أخرى دون أن تكون هذه المخاليط أصنافًا آباء للأصناف التي تحتاجها.
 
المخاليط هي الأصناف التي تحتوي على دوال متاحة من أجل استخدامها من قبل أصناف أخرى دون أن تكون هذه المخاليط أصنافًا آباء للأصناف التي تحتاجها.
  
ملاحظة: أُطلِقت ES6 بدون أي دعم للمخاليط، ولذلك لا يوجد دعم لها عندما تستخدم React مع أصناف ES6.
+
'''ملاحظة:''' أُطلِقت ES6 بدون أي دعم للمخاليط، ولذلك لا يوجد دعم لها عندما تستخدم React مع أصناف ES6.
  
وجدنا أيضًا العديد من المشاكل عند استخدام المخاليط ولا نفضّل استخدامها في الشيفرات الجديدة.
+
وجدنا أيضًا العديد من المشاكل عند استخدام المخاليط [https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html ولا نفضّل استخدامها في الشيفرات الجديدة].
  
 
يُوجَد هذا القسم فقط للتوثيق.
 
يُوجَد هذا القسم فقط للتوثيق.
  
قد تتشارك بعض المُكوِّنات المختلفة كثيرًا ببعض الوظائف. يُدعى هذا أحيانًا بالاهتمامات المشتركة (cross-cutting concerns). يُتيح لك createReactClass أن تستخدم نظام المخاليط القديم لأجل ذلك.
+
قد تتشارك بعض المُكوِّنات المختلفة كثيرًا ببعض الوظائف. يُدعى هذا أحيانًا [[wikipedia:Cross-cutting_concern|بالاهتمامات المشتركة (cross-cutting concerns)]]. يُتيح لك <code>createReactClass</code> أن تستخدم نظام المخاليط القديم لأجل ذلك.
 +
 
 +
إحدى حالات الاستخدام الشائعة هي عندما يريد المُكوّن تحديث نفسه وفق فاصلة زمنية ثابتة. من السهل استخدام الدالة <code>setInterval()</code>‎ ولكن من الهام أن تلغيها عند عدم الحاجة إليها لتوفير الذاكرة. تُزوِّدنا React [[React/react component|بتوابع دورة حياة المُكوِّنات]] والتي تُعلِمنا بوقت إنشاء أو تدمير المُكوّن. فلنُنشِئ مخلوطًا بسيطًا يستخدم هذه التوابع لإعطائنا دالة <code>setInterval()</code>‎ والتي تتوقف تلقائيًّا عند تدمير المُكوّن:<syntaxhighlight lang="javascript">
 +
var SetIntervalMixin = {
 +
  componentWillMount: function() {
 +
    this.intervals = [];
 +
  },
 +
  setInterval: function() {
 +
    this.intervals.push(setInterval.apply(null, arguments));
 +
  },
 +
  componentWillUnmount: function() {
 +
    this.intervals.forEach(clearInterval);
 +
  }
 +
};
 +
 
 +
var createReactClass = require('create-react-class');
 +
 
 +
var TickTock = createReactClass({
 +
  mixins: [SetIntervalMixin], // استخدام المخلوط
 +
  getInitialState: function() {
 +
    return {seconds: 0};
 +
  },
 +
  componentDidMount: function() {
 +
    this.setInterval(this.tick, 1000); // استدعاء تابع على المخلوط
 +
  },
 +
  tick: function() {
 +
    this.setState({seconds: this.state.seconds + 1});
 +
  },
 +
  render: function() {
 +
    return (
 +
      <p>
 +
        React قيد التشغيل منذ {this.state.seconds} ثانية.
 +
      </p>
 +
    );
 +
  }
 +
});
 +
 
 +
ReactDOM.render(
 +
  <TickTock />,
 +
  document.getElementById('example')
 +
);
 +
 
 +
</syntaxhighlight>إذا كان المُكوّن يستخدم مخاليط متعددة تُعرِّف نفس توابع دورة الحياة (أي مثلًا تريد كل هذه المخاليط إيقاف التابع <code>setInterval()</code>‎ عند تدمير المُكوّن)، فسنضمن استدعاء كافة توابع دورة الحياة. تعمل التوابع المُعرَّفة في المخاليط بنفس الترتيب الذي أوردنا فيه هذه المخاليط متبوعةً باستدعاء التابع على المُكوّن.
 +
== انظر أيضًا ==
 +
* [[React/jsx in depth|شرح JSX بالتفصيل]]
 +
* [[React/static type checking|التحقق من الأنواع الثابتة]]
 +
* [[React/typechecking with proptypes|التحقق من الأنواع باستخدام PropTypes]]
 +
* [[React/refs and the dom|استخدام المراجع مع DOM]]
 +
* [[React/uncontrolled components|المكونات غير المضبوطة]]
 +
* [[React/optimizing performance|تحسين الأداء]]
 +
* [[React/react without jsx|React بدون JSX]]
 +
* [[React/reconciliation|المطابقة (Reconciliation)]]
 +
* [[React/context|استخدام السياق (Context) في React]]
 +
* [[React/fragments|استخدام الأجزاء (Fragments) في React]]
 +
* [[React/portals|المداخل (Portals) في React]]
 +
* [[React/error boundaries|حدود الأخطاء]]
 +
* [[React/web components|مكونات الويب]]
 +
* [[React/higher order components|المكونات ذات الترتيب الأعلى]]
 +
* [[React/forwarding refs|تمرير المراجع]]
 +
* [[React/render props|خاصيات التصيير]]
 +
* [[React/integrating with other libraries|تكامل React مع المكتبات الأخرى]]
 +
* [[React/accessibility|سهولة الوصول]]
 +
* [[React/code splitting|تقسيم الشيفرة]]
 +
* [[React/strict mode|الوضع الصارم (Strict Mode)]]
  
أحد حالات الاستخدام الشائعة هي عندما يريد المُكوّن تحديث نفسه وفق فاصلة زمنية ثابتة. من السهل استخدام الدالة setInterval()‎ ولكن من الهام أن تلغيها عند عدم الحاجة إليها لتوفير الذاكرة. تُزوِّدنا React بتوابع دورة حياة المُكوِّنات والتي تُعلِمنا بوقت إنشاء أو تدمير المُكوّن. فلنُنشِئ مخلوطًا بسيطًا يستخدم هذه التوابع لإعطائنا دالة setInterval()‎ والتي تتوقف تلقائيًّا عند تدمير المُكوّن:
+
== مصادر==
 +
*[https://reactjs.org/docs/react-without-es6.html صفحة React بدون ES6 في توثيق React الرسمي].
 +
[[تصنيف:React]]
 +
[[تصنيف:React Advanced Guides]]

المراجعة الحالية بتاريخ 23:38، 3 نوفمبر 2020

نُعرِّف عادةً مُكوّنات React كأصناف JavaScript مُجرَّدة:

class Greeting extends React.Component {
  render() {
    return <h1>أهلًا {this.props.name}</h1>;
  }
}

إن لم تكن تستخدم ES6 بعد، فبإمكانك استخدام الوحدة create-react-class بدلًا من ذلك:

var createReactClass = require('create-react-class');
var Greeting = createReactClass({
  render: function() {
    return <h1>Hello, {this.props.name}</h1>;
  }
});

تُشبِه واجهة برمجة التطبيقات لأصناف ES6 الصنف createReactClass()‎ مع بعض الاستثناءات.

تعريف الخاصيات الافتراضية

تُعرَّف الخاصيّات الافتراضيّة defaultProps في أصناف ودوال ES6 كخاصيّة ضمن المُكوّن نفسه:

class Greeting extends React.Component {
  // ...
}

Greeting.defaultProps = {
  name: 'Mary'
};

أمّا باستخدام createReactClass()‎ فتحتاج لتعريف الدالة getDefaultProps()‎ كدالة ضمن الكائن المُمرَّر:

var Greeting = createReactClass({
  getDefaultProps: function() {
    return {
      name: 'Mary'
    };
  },

  // ...

});

تعيين الحالة المبدئية

في أصناف ES6 تستطيع تعريف الحالة المبدئية عن طريق تعيين this.state  في الدالة البانية:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  // ...
}

يجب عليك مع الدالة createReactClass()‎ تزويدها بتابع getInitialState منفصل والذي يُعيد الحالة المبدئية:

var Counter = createReactClass({
  getInitialState: function() {
    return {count: this.props.initialCount};
  },
  // ...
});

الربط التلقائي

تتبع التوابع في مكوّنات React المُعرَّفة كأصناف ES6 نفس القواعد في أصناف ES6 الاعتيادية. يعني هذا أنّها لا تربط this بنسخة الكائن، بل يجب عليك أن تستخدم بشكل صريح التابع ‎.bind(this)‎ في الدالة البانية:

class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'مرحبًا'};
    // هذا السطر هام
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    alert(this.state.message);
  }

  render() {
	// بما أن this.handleClick مربوط، فنستطيع استخدامه كمعالج للأحداث
    return (
      <button onClick={this.handleClick}>
        قل مرحبًا
      </button>
    );
  }
}

لا يكون هذا ضروريًّا مع createReactClass()‎ لأنّها تربط كل التوابع بشكلٍ تلقائي:

var SayHello = createReactClass({
  getInitialState: function() {
    return {message: 'مرحبًا'};
  },

  handleClick: function() {
    alert(this.state.message);
  },

  render: function() {
    return (
      <button onClick={this.handleClick}>
        قل مرحبًا
      </button>
    );
  }
});

يعني هذا أن كتابة أصناف ES6 يحتاج لكتابة شيفرة متكررة من أجل معالجات الأحداث ولكنّ الجانب الجيد هنا هو الحصول على أداء أفضل قليلًا في التطبيقات الكبيرة. إن لم تكرار كتابة الشيفرة فتستطيع تمكين صياغة خاصيّات الأصناف التجريبية مع Babel:

class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'مرحبًا'};
  }
  // تحذير: هذه الصياغة تجريبية
  // استخدام السهم هنا يربط التابع
  handleClick = () => {
    alert(this.state.message);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        مرحبًا
      </button>
    );
  }
}

انتبه إلى أنّ هذه الصياغة تجريبية وبالتالي قد تتغير أو لا تبقى موجودة أصلًا.

إن كنت تفضّل البقاء بأمان فلديك بعض الخيارات:

  • ربط التوابع في الدالة البانية.
  • استخدام الدوال السهمية، مثل ‎onClick={(e) => this.handleClick(e)}‎.
  • الاستمرار في استخدام createReactClass.

المخاليط (Mixins)

المخاليط هي الأصناف التي تحتوي على دوال متاحة من أجل استخدامها من قبل أصناف أخرى دون أن تكون هذه المخاليط أصنافًا آباء للأصناف التي تحتاجها.

ملاحظة: أُطلِقت ES6 بدون أي دعم للمخاليط، ولذلك لا يوجد دعم لها عندما تستخدم React مع أصناف ES6.

وجدنا أيضًا العديد من المشاكل عند استخدام المخاليط ولا نفضّل استخدامها في الشيفرات الجديدة.

يُوجَد هذا القسم فقط للتوثيق.

قد تتشارك بعض المُكوِّنات المختلفة كثيرًا ببعض الوظائف. يُدعى هذا أحيانًا بالاهتمامات المشتركة (cross-cutting concerns). يُتيح لك createReactClass أن تستخدم نظام المخاليط القديم لأجل ذلك.

إحدى حالات الاستخدام الشائعة هي عندما يريد المُكوّن تحديث نفسه وفق فاصلة زمنية ثابتة. من السهل استخدام الدالة setInterval()‎ ولكن من الهام أن تلغيها عند عدم الحاجة إليها لتوفير الذاكرة. تُزوِّدنا React بتوابع دورة حياة المُكوِّنات والتي تُعلِمنا بوقت إنشاء أو تدمير المُكوّن. فلنُنشِئ مخلوطًا بسيطًا يستخدم هذه التوابع لإعطائنا دالة setInterval()‎ والتي تتوقف تلقائيًّا عند تدمير المُكوّن:

var SetIntervalMixin = {
  componentWillMount: function() {
    this.intervals = [];
  },
  setInterval: function() {
    this.intervals.push(setInterval.apply(null, arguments));
  },
  componentWillUnmount: function() {
    this.intervals.forEach(clearInterval);
  }
};

var createReactClass = require('create-react-class');

var TickTock = createReactClass({
  mixins: [SetIntervalMixin], // استخدام المخلوط
  getInitialState: function() {
    return {seconds: 0};
  },
  componentDidMount: function() {
    this.setInterval(this.tick, 1000); // استدعاء تابع على المخلوط
  },
  tick: function() {
    this.setState({seconds: this.state.seconds + 1});
  },
  render: function() {
    return (
      <p>
        React قيد التشغيل منذ {this.state.seconds} ثانية.
      </p>
    );
  }
});

ReactDOM.render(
  <TickTock />,
  document.getElementById('example')
);

إذا كان المُكوّن يستخدم مخاليط متعددة تُعرِّف نفس توابع دورة الحياة (أي مثلًا تريد كل هذه المخاليط إيقاف التابع setInterval()‎ عند تدمير المُكوّن)، فسنضمن استدعاء كافة توابع دورة الحياة. تعمل التوابع المُعرَّفة في المخاليط بنفس الترتيب الذي أوردنا فيه هذه المخاليط متبوعةً باستدعاء التابع على المُكوّن.

انظر أيضًا

 مصادر