الفرق بين المراجعتين ل"React/hooks state"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(اكمال إضافة الصفحة)
(تحديث)
 
(مراجعة متوسطة واحدة بواسطة مستخدم واحد آخر غير معروضة)
سطر 21: سطر 21:
  
 
== مثال عن صنف مكافئ لخطاف ==
 
== مثال عن صنف مكافئ لخطاف ==
إن استعملت الأصناف في [[React]] من قبل، فيجب أن تكون الشيفرة التالية مألوفة لديك:<syntaxhighlight lang="javascript">
+
إن استعملت الأصناف في [[React]] من قبل، فيجب أن تكون الشيفرة التالية مألوفةً لديك:<syntaxhighlight lang="javascript">
 
class Example extends React.Component {
 
class Example extends React.Component {
 
   constructor(props) {
 
   constructor(props) {
سطر 41: سطر 41:
 
   }
 
   }
 
}
 
}
 +
 
</syntaxhighlight>الحالة الأولية تكون <code>{ count: 0 }</code>، ونعمل على زيادة <code>state.count</code> عندما يضغط المستخدم على زر يستدعي <code>this.setState()‎</code>. سنستعمل أجزاء من هذا الصنف في أقسام لاحقة من هذه الصفحة.
 
</syntaxhighlight>الحالة الأولية تكون <code>{ count: 0 }</code>، ونعمل على زيادة <code>state.count</code> عندما يضغط المستخدم على زر يستدعي <code>this.setState()‎</code>. سنستعمل أجزاء من هذا الصنف في أقسام لاحقة من هذه الصفحة.
  
'''ملاحظة''': قد تتساءل عن سبب استعمالنا عدادًا هنا عوضَ استعمال مثال أكثر واقعية. يكمن السبب في أن هذا المثال يساعدنا على التركيز على الواجهة البرمجية في بداية رحلتنا مع الخطافات.
+
'''ملاحظة''': قد تتساءل عن سبب استعمالنا مثال عدَّادٍ هنا عوضَ استعمال مثال أكثر واقعية. يكمن السبب في أنَّ هذا المثال البسيط يساعدنا على التركيز على الواجهة البرمجية في بداية رحلتنا مع الخطافات.
  
 
== الخطافات ومكونات دالة ==
 
== الخطافات ومكونات دالة ==
سطر 56: سطر 57:
 
   return <div />;
 
   return <div />;
 
}
 
}
</syntaxhighlight>ربما كنت تعرف مسبقًا أن هذه المكونات هي "مكونات عديمة الحالة" (stateless components). نحن الآن نعرِّف إمكانية استعمال حالة [[React]] من هذه المكونات، لذا نفضل الاسم "مكونات دالة".
+
</syntaxhighlight>ربما كنت تعرف مسبقًا أنَّ هذه المكونات هي "مكونات عديمة الحالة" (stateless components). نعرِّف الآن إمكانية استعمال حالة [[React]] من هذه المكونات، لذا نفضل استعمال الاسم "مكونات دالة".
  
لا تعمل الخطافات داخل الأصناف، ولكن يمكن استعمالها بدلًا من كتابة أصناف.
+
لا تعمل الخطافات داخل الأصناف، ولكن يمكن استعمالها بدلًا من الأصناف نفسها.
  
 
== ما هو الخطاف؟ ==
 
== ما هو الخطاف؟ ==
سطر 71: سطر 72:
 
'''متى يمكنني استعمال الخطاف؟'''
 
'''متى يمكنني استعمال الخطاف؟'''
  
إن كتبت مكون دالة ووجدت أنك بحاجة إلى إضافة بعض الحالة له، فستحتاج - سابقًا قبل عصر الخطافات - إلى تحويله إلى صنف. الآن، يمكنك استعمال خطاف داخل مكون دالة موجودة وهو ما سنفعله الآن.
+
إن كتبت مكون دالة ووجدت أنَّك بحاجة إلى إضافة بعض الحالة له، فستحتاج - سابقًا قبل عصر الخطافات - إلى تحويله إلى صنف. الآن، يمكنك استعمال خطاف داخل مكون دالة موجودة وهو ما سنفعله الآن.
  
'''ملاحظة''': هنالك بعض القواعد المخصصة تحدد المكان المسموح والمحظور فيه استعمال الخطافات ضمن مكون. سنشرح هذه القواعد بالتفصيل الممل في توثيق [[React/hooks rules|قواعد استعمال الخطافات]].
+
'''ملاحظة''': هنالك بعض [[React/hooks rules|القواعد المخصَّصة]] تحدِّد المكان المسموح والمحظور فيه استعمال الخطافات ضمن مكون. سنشرح هذه القواعد بالتفصيل الممل في توثيق [[React/hooks rules|قواعد استعمال الخطافات]].
  
 
== التصريح عن متغير حالة ==
 
== التصريح عن متغير حالة ==
سطر 84: سطر 85:
 
     };
 
     };
 
   }
 
   }
</syntaxhighlight>في مكون دالة، لا يمكننا استعمال <code>this</code>، لذا لا نستطيع إسناد إو قراء <code>this.state</code>. عوض ذلك، يمكننا استدعاء الخطاف <code>useState</code> مباشرةً داخل المكون الخاص بنا:<syntaxhighlight lang="javascript">
+
</syntaxhighlight>في مكون دالة، لا يمكننا استعمال <code>this</code>، لذا لا نستطيع إسناد أو قراء <code>this.state</code>. عوض ذلك، يمكننا استدعاء الخطاف <code>useState</code> مباشرةً داخل المكون الخاص بنا:<syntaxhighlight lang="javascript">
 
import React, { useState } from 'react';
 
import React, { useState } from 'react';
  
سطر 100: سطر 101:
 
'''ما الذي يعيده <code>useState</code>؟'''
 
'''ما الذي يعيده <code>useState</code>؟'''
  
إنه يعيد زوجًا من القيم: الحالة الحالية، ودالة تحدِّثها. لهذا السبب، نكتب <code>const [count, setCount] = useState()‎</code>. هذا الأمر يشبه <code>this.state.count</code> و <code>this.setState</code> في الصنف، باستثناء أننا نحصل عليهم كزوج من القيم. إن لم تكن الصيغة السابقة التي استعملناها مألوفة لك، فسنتطرق إليها في آخر هذه الصفحة.
+
إنه يعيد زوجًا من القيم: الحالة الحالية، ودالة تحدِّثها. لهذا السبب، نكتب <code>const [count, setCount] = useState()‎</code>. هذا الأمر يشبه <code>this.state.count</code> و <code>this.setState</code> في الصنف، باستثناء أنَّنا نحصل عليهم كزوج من القيم. إن لم تكن الصيغة السابقة التي استعملناها مألوفة لك، فسنتطرق إليها في [[React/hooks state#.D8.A5.D8.B6.D8.A7.D9.81.D8.A9: .D9.85.D8.A7 .D8.A7.D9.84.D8.B0.D9.8A .D8.AA.D8.B9.D9.86.D9.8A.D9.87 .D8.A7.D9.84.D8.A3.D9.82.D9.88.D8.A7.D8.B3 .D8.A7.D9.84.D9.85.D8.B9.D9.82.D9.88.D9.81.D8.A9.D8.9F|آخر هذه الصفحة]].
  
 
الآن وقد عرفنا ما الذي يفعله الخطاف <code>useState</code>، يجب أن تكون الشيفرة التالية مفهومة تمامًا لك:<syntaxhighlight lang="javascript">
 
الآن وقد عرفنا ما الذي يفعله الخطاف <code>useState</code>، يجب أن تكون الشيفرة التالية مفهومة تمامًا لك:<syntaxhighlight lang="javascript">
سطر 108: سطر 109:
 
   // "count" التصريح عن متغير حالة جديد ندعوه
 
   // "count" التصريح عن متغير حالة جديد ندعوه
 
   const [count, setCount] = useState(0);
 
   const [count, setCount] = useState(0);
</syntaxhighlight>صرَّحنا عن متغير حالة يدعى <code>count</code>، وأسندنا القيمة 0 العددية له. ستتذكر [[React]] قيمته الاحلية بين عمليات إعادة التصيير، وتوفر الحالة الأحدث له للدالة. إ نأردنا تحديث قيمة المتغير <code>count</code> الحالية، يمكننا استدعاء <code>useState</code>.
+
</syntaxhighlight>صرَّحنا عن متغير حالة يدعى <code>count</code>، وأسندنا القيمة 0 العددية له. ستتذكر [[React]] قيمته الحالية بين عمليات إعادة التصيير، وتوفر الحالة الأحدث له للدالة. إن أردنا تحديث قيمة المتغير <code>count</code> الحالية، يمكننا استدعاء <code>useState</code>.
  
'''ملاحظة''': قد تتسائل عن سبب استعمال الاسم <code>useState</code> لهذا الخطاف وليس الاسم <code>createState</code>؟ الجواب هو أن "إنشاء" (create) لن تكون دقيقة والسبب أنَّ الحالة تُنشَأ عندما يصيَّر المكون أول مرة. في عمليات التصيير اللاحقة، يعطينا الخطاف <code>useState</code> القيمة (الحالة) الحالية وإلا لما كنا أطلقنا عليها "حالة" (state) على الإطلاق. هنالك أيضًا سبب متعلق ببدء تسمية الخطافات بالكلمة <code>use</code>، وسنتعرف عليه في توثيق "[[React/hooks rules|قواعد استعمال الخطافات]]".
+
'''ملاحظة''': قد تتسائل عن سبب استعمال الاسم <code>useState</code> لهذا الخطاف وليس الاسم <code>createState</code>؟ الجواب هو أنَّ "إنشاء" (create) لن تكون دقيقة والسبب أنَّ الحالة تُنشَأ عندما يصيَّر المكون أول مرة فقط. في عمليات التصيير اللاحقة، يعطينا الخطاف <code>useState</code> القيمة (الحالة) الحالية وإلا لما كنا أطلقنا عليها "حالة" (state) على الإطلاق. هنالك أيضًا سبب متعلق ببدء تسمية الخطافات بالكلمة <code>use</code>، وسنتعرف عليه في توثيق "[[React/hooks rules|قواعد استعمال الخطافات]]".
  
 
== قراءة الحالة ==
 
== قراءة الحالة ==
إن أردنا إظهار قيمة المتغير <code>count</code> الحالية في صنف، يمكنن أن نقرأ <code>this.state.count</code>:<syntaxhighlight lang="html">
+
إن أردنا إظهار قيمة المتغير <code>count</code> الحالية في صنف، يمكن أن نقرأ <code>this.state.count</code>:<syntaxhighlight lang="html">
 
<p>You clicked {this.state.count} times</p>
 
<p>You clicked {this.state.count} times</p>
</syntaxhighlight>في دال، يمكننا استعمال المتغير <code>count</code> مباشرةً:<syntaxhighlight lang="html">
+
</syntaxhighlight>يمكننا استعمال المتغير <code>count</code> في الدوال مباشرةً:<syntaxhighlight lang="html">
 
<p>You clicked {count} times</p>
 
<p>You clicked {count} times</p>
  
سطر 150: سطر 151:
 
* '''السطر 1''': استوردنا الخطاف <code>useState</code> من [[React]]. هذا يمكننا من إبقاء حالة محلية (local state) في مكون دالة.
 
* '''السطر 1''': استوردنا الخطاف <code>useState</code> من [[React]]. هذا يمكننا من إبقاء حالة محلية (local state) في مكون دالة.
  
* '''السطر 4''': داخل المكون <code>Example</code>، صرَّحنا عن متغير حالة جديد عبر استدعاء الخطاف <code>useState</code>. يعيد الخطاف زوجًا من القيم أعطينا لكل من هاتين القيمتين اسمًا. سنتحاج إلى استدعاء المتغير <code>count</code> لأنه يحمل عدد ضغطات الزر. هيَّأنا هذا المتغير إلى القيمة 0 عبر تمرير هذه القيمة إلى <code>useState</code>. القيمة الثانية من الزوج الذي يعيده الخطاف هي دالة بحد ذاتها. هذه الدالة تحدِّث المتغير <code>count</code>، لذا سنطلق عليها <code>setCount</code>.
+
* '''السطر 4''': داخل المكون <code>Example</code>، صرَّحنا عن متغير حالة جديد عبر استدعاء الخطاف <code>useState</code>. يعيد الخطاف زوجًا من القيم أعطينا لكل من هاتين القيمتين اسمًا. سنتحاج إلى استدعاء المتغير <code>count</code> لأنَّه يحمل عدد ضغطات الزر. هيَّأنا هذا المتغير إلى القيمة 0 عبر تمرير هذه القيمة إلى <code>useState</code>. القيمة الثانية من الزوج الذي يعيده الخطاف هي دالة بحد ذاتها. هذه الدالة تحدِّث المتغير <code>count</code>، لذا سنطلق عليها <code>setCount</code>.
  
 
* '''السطر 9''': عندما يضغط المستخدم على الزر، تُستدعَى الدالة <code>setCount</code> مع القيمة الجديدة. ستعيد [[React]] بعد ذلك تصيير المكون <code>Example</code> مع تمرير القيمة <code>count</code> الجديدة إليه.
 
* '''السطر 9''': عندما يضغط المستخدم على الزر، تُستدعَى الدالة <code>setCount</code> مع القيمة الجديدة. ستعيد [[React]] بعد ذلك تصيير المكون <code>Example</code> مع تمرير القيمة <code>count</code> الجديدة إليه.
قد يبدو للوهلة الأولى أن هذا كثير ويحتاج إلى فهم وتركيز كبيرة. لا تتسرع بالحكم. إن شعرت أنك قد فقدت تركيزك أثناء الشرح، أعد قراءة الشيفرات بدءًا من بداية الدرس مجددًا وحاول فهم كل سطر منها. نعدك إن نسيت (مؤقتًا) كيفية عمل الحالة في الأصناف ونظرت إلى الشيفرة مجدَّدًا، فستفهمها بشكل كامل.
+
قد يبدو للوهلة الأولى أنَّ هذا كثير ويحتاج إلى فهم وتركيز كبيرين. لا تتسرع بالحكم. إن شعرت أنَّك قد فقدت تركيزك أثناء الشرح، حضِّر كوبًا من القهوة ثمَّ اشربه مع إعادة قراءة الشيفرات بدءًا من بداية الدرس وحاول فهم كل سطر منها. نعدك إن نسيت (مؤقتًا) كيفية عمل الحالة في الأصناف ونظرت إلى الشيفرة مجدَّدًا، فستفهمها بشكل كامل.
  
=== إضافة: ما الذي تعنيه الأقواس المعقوفة؟ ===
+
=== ما الذي تعنيه الأقواس المعقوفة؟ ===
لابد أنك لاحظ وجود أقواس معقوفة عند التصريح عن متغير حالة:<syntaxhighlight lang="javascript">
+
لابد أنَّك لاحظ وجود أقواس معقوفة عند التصريح عن متغير حالة:<syntaxhighlight lang="javascript">
 
const [count, setCount] = useState(0);
 
const [count, setCount] = useState(0);
  
 
</syntaxhighlight>الأسماء في القسم الأيسر ليست جزءًا من واجهة [[React]] البرمجية. يمكنك أن تسمي متغيرات الحالة الخاصة بك بأي اسم تريد:<syntaxhighlight lang="javascript">
 
</syntaxhighlight>الأسماء في القسم الأيسر ليست جزءًا من واجهة [[React]] البرمجية. يمكنك أن تسمي متغيرات الحالة الخاصة بك بأي اسم تريد:<syntaxhighlight lang="javascript">
 
const [fruit, setFruit] = useState('banana');
 
const [fruit, setFruit] = useState('banana');
</syntaxhighlight>هذه الصيغة هي إحدى صيغ جافاسكربت يطلق عليها "[[JavaScript/Destructuring Assignment|تفكيك المصفوفات]]". إنها تعني أننا نريد إنشاء متغيِّرين جديدين هما: <code>fruit</code> و <code>setFruit</code>، إذ الأول يعيَّن إلى أول قيمة يعيدها <code>useState</code>، والثاني يعين إلى القيمة الثانية المعادة. هذا يكافئ الشيفرة التالية:<syntaxhighlight lang="javascript">
+
</syntaxhighlight>هذه الصيغة هي إحدى صيغ [[JavaScript]] التي يطلق عليها "[[JavaScript/Destructuring Assignment|تفكيك المصفوفات]]". إنَّها تعني أنَّنا نريد إنشاء متغيِّرين جديدين هما: <code>fruit</code> و <code>setFruit</code>، إذ يعيَّن الأول إلى أول قيمة يعيدها <code>useState</code>، والثاني إلى القيمة الثانية المعادة. هذا يكافئ الشيفرة التالية:<syntaxhighlight lang="javascript">
 
var fruitStateVariable = useState('banana'); // يعيد زوجًا
 
var fruitStateVariable = useState('banana'); // يعيد زوجًا
 
var fruit = fruitStateVariable[0]; // أول عنصر من الزوج
 
var fruit = fruitStateVariable[0]; // أول عنصر من الزوج
 
var setFruit = fruitStateVariable[1]; // ثاني عنصر من الزوج
 
var setFruit = fruitStateVariable[1]; // ثاني عنصر من الزوج
</syntaxhighlight>عندما صرحنا عن متغير حالة مع <code>useState</code>، فإن هذا الخطاف يعيد زوجًا من القيم في مصفوفة بعنصرين. العنصر الأولي هو القيمة الحالية، والعنصر الثاني هو الدالة التي تمكننا من تحديثها. استعمال <code>[0]</code> و <code>[1]</code> للوصول إلى هاتين القيمتين أمرٌ مربك لأن لهما معنى محدَّد. هذا هو سبب استعمالنا أسلوك [[JavaScript/Destructuring Assignment|الإسناد بالتفكيك]] عوضًا عن ذلك.
+
</syntaxhighlight>عندما صرَّحنا عن متغير حالة مع <code>useState</code>، فإنَّ هذا الخطاف يعيد زوجًا من القيم في مصفوفة بعنصرين. العنصر الأولي هو القيمة الحالية، والعنصر الثاني هو الدالة التي تمكننا من تحديثها. استعمال <code>[0]</code> و <code>[1]</code> للوصول إلى هاتين القيمتين أمرٌ مربك لأنَّ لهما معنى محدَّد. هذا هو سبب استعمالنا أسلوك [[JavaScript/Destructuring Assignment|الإسناد بالتفكيك]] عوضًا عن ذلك.
  
'''ملاحظة''': ربما انتابك شيءٌ من الفضول حول كيفية معرفة [[React]] أي مكون يقابل <code>useState</code> لمَّا كنا نعيد تمرير أي شي مثل <code>this</code> إلى [[React]].لا تقلق، سنجيب عن هذا السؤال وأسئلة أخرى في صفحة [[React/hooks faq|الأسئلة الشائعة حول الخطافات]].
+
'''ملاحظة''': ربما انتابك شيءٌ من الفضول حول كيفية معرفة [[React]] أي مكون يقابل <code>useState</code> لمَّا كنا نعيد تمرير أي شي مثل <code>this</code> إلى [[React]]. لا تقلق، سنجيب عن هذا السؤال وأسئلة أخرى في صفحة [[React/hooks faq#.D9.83.D9.8A.D9.81 .D8.AA.D8.B1.D8.A8.D8.B7 React .D8.A7.D8.B3.D8.AA.D8.AF.D8.B9.D8.A7.D8.A1.D8.A7.D8.AA .D8.A7.D9.84.D8.AE.D8.B7.D8.A7.D9.81.D8.A7.D8.AA .D9.85.D8.B9 .D8.A7.D9.84.D9.85.D9.83.D9.88.D9.86.D8.A7.D8.AA.|الأسئلة الشائعة حول الخطافات]].
  
 
=== إضافة: استعمال متغيرات حالة عديدة ===
 
=== إضافة: استعمال متغيرات حالة عديدة ===
سطر 195: سطر 196:
 
*[[React/hooks intro|مدخل إلى الخطافات]]
 
*[[React/hooks intro|مدخل إلى الخطافات]]
 
*[[React/hooks overview|لمحة خاطفة عن الخطافات]]
 
*[[React/hooks overview|لمحة خاطفة عن الخطافات]]
*خطاف الحالة  (الصفحة الحالية)
 
 
*[[React/hooks effect|خطاف التأثير]]
 
*[[React/hooks effect|خطاف التأثير]]
 
*[[React/hooks rules|قواعد استعمال الخطافات]]
 
*[[React/hooks rules|قواعد استعمال الخطافات]]

المراجعة الحالية بتاريخ 11:02، 6 نوفمبر 2020

الخطافات هي إضافة جديدة إلى الإصدار 16.8 في React، إذ تسمح لك باستعمال ميزة الحالة وميزات React الأخرى دون كتابة أي صنف.

شرحت الصفحة السابقة في قسم خطاف الحالة هذا الخطاف عبر المثال التالي:

import React, { useState } from 'react';

function Example() {
  // "count" التصريح عن متغير حالة جديد ندعوه
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

بادئ ذي بدء، سنتعرف على الخطافات عبر موازنة هذه الشيفرة مع الصنف المكافئ لها.

مثال عن صنف مكافئ لخطاف

إن استعملت الأصناف في React من قبل، فيجب أن تكون الشيفرة التالية مألوفةً لديك:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

الحالة الأولية تكون { count: 0 }، ونعمل على زيادة state.count عندما يضغط المستخدم على زر يستدعي this.setState()‎. سنستعمل أجزاء من هذا الصنف في أقسام لاحقة من هذه الصفحة.

ملاحظة: قد تتساءل عن سبب استعمالنا مثال عدَّادٍ هنا عوضَ استعمال مثال أكثر واقعية. يكمن السبب في أنَّ هذا المثال البسيط يساعدنا على التركيز على الواجهة البرمجية في بداية رحلتنا مع الخطافات.

الخطافات ومكونات دالة

لنتذكر سويةً، تبدو مكونات دالة في React بالشكل:

const Example = (props) => {
  // تستطيع استعمال الخطافات هنا
  return <div />;
}

أو الشكل التالي:

function Example(props) {
  // تستطيع استعمال الخطافات هنا
  return <div />;
}

ربما كنت تعرف مسبقًا أنَّ هذه المكونات هي "مكونات عديمة الحالة" (stateless components). نعرِّف الآن إمكانية استعمال حالة React من هذه المكونات، لذا نفضل استعمال الاسم "مكونات دالة".

لا تعمل الخطافات داخل الأصناف، ولكن يمكن استعمالها بدلًا من الأصناف نفسها.

ما هو الخطاف؟

يبدأ مثالنا الجديد باستيراد الخطاف useState من React:

import React, { useState } from 'react';

function Example() {
  // ...
}

إذًا، ما هو الخطاف تحديدًا؟ الخطاف هو دالة مميزة تمكنك من "تعليق أو ربط" (hook into) ميزات React مع بعضها. على سبيل المثال، useState هو خطاف يمكنك من إضافة حالة React إلى مكونات دالة. سنتطرق إلى الخطافات الأخرى لاحقًا.

متى يمكنني استعمال الخطاف؟

إن كتبت مكون دالة ووجدت أنَّك بحاجة إلى إضافة بعض الحالة له، فستحتاج - سابقًا قبل عصر الخطافات - إلى تحويله إلى صنف. الآن، يمكنك استعمال خطاف داخل مكون دالة موجودة وهو ما سنفعله الآن.

ملاحظة: هنالك بعض القواعد المخصَّصة تحدِّد المكان المسموح والمحظور فيه استعمال الخطافات ضمن مكون. سنشرح هذه القواعد بالتفصيل الممل في توثيق قواعد استعمال الخطافات.

التصريح عن متغير حالة

إن كنا سنستعمل صنفًا، نهيِّئ فيه الحالة count إلى 0 عبر ضبط this.state إلى { count: 0 } في باني هذا الصنف:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

في مكون دالة، لا يمكننا استعمال this، لذا لا نستطيع إسناد أو قراء this.state. عوض ذلك، يمكننا استدعاء الخطاف useState مباشرةً داخل المكون الخاص بنا:

import React, { useState } from 'react';

function Example() {
  // "count" التصريح عن متغير حالة جديد ندعوه
  const [count, setCount] = useState(0);

ماذا يفعل استدعاء useState؟

إنَّه يصرِّح عن "متغير حالة" (state variable). هذا المتغير يدعى count ولكن يمكننا أن ندعوه بأي اسم آخر مثل banana. هذه هي طريقة لحفظ بعض القيم بين استدعاءات الدالة، إذ useState هي طريقة جديدة لاستعمال الامكانيات نفسها التي توفرها this.state في الصنف. عمومًا، المتغيرات "تختفي" عند اكتمال تنفيذ الدالة وخروجها ولكن متغيرات الحالة تحافظ على قيمتها في React.

لماذا نمرر وسيطًا إلى useState؟

الوسيط الوحيد الذي يمكن تمريره إلى الخطاف useState()‎ هو الحالة الأولية. خلافًا للأصناف، ليس من الضروري أن تكون الحالة كائنًا. يمكننا استعمال عدد أو سلسلة نصية إن كان ذلك ما نحتاجه. في مثالنا، نحتاج إلى عدد ليمثل عدد المرات التي ضغط فيها المستخدم على الزر، لذا مرَّرنا العدد 0 ليكون الحالة الأولية لمتغيرنا. (إن أردنا تخزين قيمتين مختلفتين في حالة، فيمكننا فعل ذلك عبر استدعاء useState()‎ مرتين.)

ما الذي يعيده useState؟

إنه يعيد زوجًا من القيم: الحالة الحالية، ودالة تحدِّثها. لهذا السبب، نكتب const [count, setCount] = useState()‎. هذا الأمر يشبه this.state.count و this.setState في الصنف، باستثناء أنَّنا نحصل عليهم كزوج من القيم. إن لم تكن الصيغة السابقة التي استعملناها مألوفة لك، فسنتطرق إليها في آخر هذه الصفحة.

الآن وقد عرفنا ما الذي يفعله الخطاف useState، يجب أن تكون الشيفرة التالية مفهومة تمامًا لك:

import React, { useState } from 'react';

function Example() {
  // "count" التصريح عن متغير حالة جديد ندعوه
  const [count, setCount] = useState(0);

صرَّحنا عن متغير حالة يدعى count، وأسندنا القيمة 0 العددية له. ستتذكر React قيمته الحالية بين عمليات إعادة التصيير، وتوفر الحالة الأحدث له للدالة. إن أردنا تحديث قيمة المتغير count الحالية، يمكننا استدعاء useState.

ملاحظة: قد تتسائل عن سبب استعمال الاسم useState لهذا الخطاف وليس الاسم createState؟ الجواب هو أنَّ "إنشاء" (create) لن تكون دقيقة والسبب أنَّ الحالة تُنشَأ عندما يصيَّر المكون أول مرة فقط. في عمليات التصيير اللاحقة، يعطينا الخطاف useState القيمة (الحالة) الحالية وإلا لما كنا أطلقنا عليها "حالة" (state) على الإطلاق. هنالك أيضًا سبب متعلق ببدء تسمية الخطافات بالكلمة use، وسنتعرف عليه في توثيق "قواعد استعمال الخطافات".

قراءة الحالة

إن أردنا إظهار قيمة المتغير count الحالية في صنف، يمكن أن نقرأ this.state.count:

<p>You clicked {this.state.count} times</p>

يمكننا استعمال المتغير count في الدوال مباشرةً:

<p>You clicked {count} times</p>

تحديث الحالة

في الصنف، نحتاج إلى استدعاء this.setState()‎ لتحديث الحالة count:

<button onClick={() => this.setState({ count: this.state.count + 1 })}>
  Click me
</button>

في الدالة، لدينا setState و count مسبقًا كمتغيرات، لذا لا تحتاج إلى this:

<button onClick={() => setCount(count + 1)}>
  Click me
</button>

الخلاصة

لنراجع ما تعلمناه بالمرور على كل سطر من أسطر الشيفرة والتأكد من فهمنا للخطافات بشكل عام ولخطاف الحالة بشكل خاص:

 1 import React, { useState } from 'react';
 2 
 3 function Example() {
 4    const [count, setCount] = useState(0);
 5 
 6   return (
 7     <div>
 8       <p>You clicked {count} times</p>
 9       <button onClick={() => setCount(count + 1)}>
10        Click me
11       </button>
12     </div>
13   );
14 }
  • السطر 1: استوردنا الخطاف useState من React. هذا يمكننا من إبقاء حالة محلية (local state) في مكون دالة.
  • السطر 4: داخل المكون Example، صرَّحنا عن متغير حالة جديد عبر استدعاء الخطاف useState. يعيد الخطاف زوجًا من القيم أعطينا لكل من هاتين القيمتين اسمًا. سنتحاج إلى استدعاء المتغير count لأنَّه يحمل عدد ضغطات الزر. هيَّأنا هذا المتغير إلى القيمة 0 عبر تمرير هذه القيمة إلى useState. القيمة الثانية من الزوج الذي يعيده الخطاف هي دالة بحد ذاتها. هذه الدالة تحدِّث المتغير count، لذا سنطلق عليها setCount.
  • السطر 9: عندما يضغط المستخدم على الزر، تُستدعَى الدالة setCount مع القيمة الجديدة. ستعيد React بعد ذلك تصيير المكون Example مع تمرير القيمة count الجديدة إليه.

قد يبدو للوهلة الأولى أنَّ هذا كثير ويحتاج إلى فهم وتركيز كبيرين. لا تتسرع بالحكم. إن شعرت أنَّك قد فقدت تركيزك أثناء الشرح، حضِّر كوبًا من القهوة ثمَّ اشربه مع إعادة قراءة الشيفرات بدءًا من بداية الدرس وحاول فهم كل سطر منها. نعدك إن نسيت (مؤقتًا) كيفية عمل الحالة في الأصناف ونظرت إلى الشيفرة مجدَّدًا، فستفهمها بشكل كامل.

ما الذي تعنيه الأقواس المعقوفة؟

لابد أنَّك لاحظ وجود أقواس معقوفة عند التصريح عن متغير حالة:

const [count, setCount] = useState(0);

الأسماء في القسم الأيسر ليست جزءًا من واجهة React البرمجية. يمكنك أن تسمي متغيرات الحالة الخاصة بك بأي اسم تريد:

const [fruit, setFruit] = useState('banana');

هذه الصيغة هي إحدى صيغ JavaScript التي يطلق عليها "تفكيك المصفوفات". إنَّها تعني أنَّنا نريد إنشاء متغيِّرين جديدين هما: fruit و setFruit، إذ يعيَّن الأول إلى أول قيمة يعيدها useState، والثاني إلى القيمة الثانية المعادة. هذا يكافئ الشيفرة التالية:

var fruitStateVariable = useState('banana'); // يعيد زوجًا
var fruit = fruitStateVariable[0]; // أول عنصر من الزوج
var setFruit = fruitStateVariable[1]; // ثاني عنصر من الزوج

عندما صرَّحنا عن متغير حالة مع useState، فإنَّ هذا الخطاف يعيد زوجًا من القيم في مصفوفة بعنصرين. العنصر الأولي هو القيمة الحالية، والعنصر الثاني هو الدالة التي تمكننا من تحديثها. استعمال [0] و [1] للوصول إلى هاتين القيمتين أمرٌ مربك لأنَّ لهما معنى محدَّد. هذا هو سبب استعمالنا أسلوك الإسناد بالتفكيك عوضًا عن ذلك.

ملاحظة: ربما انتابك شيءٌ من الفضول حول كيفية معرفة React أي مكون يقابل useState لمَّا كنا نعيد تمرير أي شي مثل this إلى React. لا تقلق، سنجيب عن هذا السؤال وأسئلة أخرى في صفحة الأسئلة الشائعة حول الخطافات.

إضافة: استعمال متغيرات حالة عديدة

التصريح عن متغيرات حالة كأزواج من [something, setSomething] هو أمر عملي وجيد، إذ يسمح لنا بإعطاء أسماء مختلفة لمتغيرات مختلفة للحالة إن أردنا استعمال أكثر من متغير حالة واحد:

function ExampleWithManyStates() {
  // التصريح عن متغيرات حالة عديدة
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);

في هذا المكون في الشيفرة الآنفة، لدينا المتغيرات age، و fruit، و todos بوصفها متغيرات حالة، ويمكننا تحديث كل منها على حدة:

function handleOrangeClick() {
    // this.setState({ fruit: 'orange' }) يشبه
    setFruit('orange');
  }

لا يتوجب عليه استعمال عدة متغيرات حالة. متغيرات الحالة يمكنها أن تحوي كائنات ومصفوفات، لذا لا يزال بإمكانك تجميع البيانات المترابطة مع بعضها بعضًا. على أي حال، تحديث متغير حالة يستبدل دومًا قيمته بدلًا من دمجها، وهذا يخالف سلوك this.setState في الأصناف.

أعطينا الكثير من التوصيات حول فصل متغيرات الحالة المستقلة في صفحة الأسئلة الشائعة حول الخطافات.

الخطوات التالية

تعلمنا حول أحد الخطافات التي توفرها React وهو الخطاف useState. في أغلب الأحيان، سنشير إليه بالاسم "خطاف الحالة" (State Hook). يسمح لنا هذا الخطاف بإضافة حالة محلية إلى مكونات دالة في React بخطوات بسيطة وشيفرة أقل.

تعلمنا أيضًا القليل حول ماهية الخطافات. كما رأينا، الخطافات هي دوال تمكنك من "تعليق أو ربط" (hook into) ميزات React من مكونات دالة. أسماء الخطافات تبدأ دومًا بالكلمة use، وهنالك الكثير من الخطافات التي لم نرها بعد.

لنكمل الآن وننتقل إلى الخطاف التالي وهو الخطاف useEffect. يسمح لنا هذا الخطاف بتنفيذ تأثيرات جانبية (side effects) في المكونات، وهو يشبه توابع دورة الحياة في الأصناف.

 انظر أيضًا

 مصادر