الفرق بين المراجعتين لصفحة: «React/hooks overview»
جميل-بيلوني (نقاش | مساهمات) إنشاء الصفحة |
تحديث |
||
(مراجعتان متوسطتان بواسطة مستخدم واحد آخر غير معروضتين) | |||
سطر 1: | سطر 1: | ||
''الخطافات هي إضافة جديدة إلى الإصدار 16.8 في React، إذ تسمح لك باستعمال ميزة الحالة | <noinclude>{{DISPLAYTITLE:لمحة خاطفة عن الخطافات في React}}</noinclude> | ||
''الخطافات هي إضافة جديدة إلى الإصدار 16.8 في React، إذ تسمح لك باستعمال ميزة الحالة وميزات React الأخرى دون كتابة أي صنف.'' | |||
الخطافات متوافقة مع ما سبقها بشكل كامل. توفر هذه الصفحة نظرة عامة | الخطافات متوافقة مع ما سبقها بشكل كامل. توفر هذه الصفحة نظرة عامة وسريعة حول الخطافات لمستخدمي [[React]] ذوي الخبرة. إن ازددت حيرةً في بعض المواضع أثناء قراءة هذه الصفحة، فانتقل إلى الرابط المذكور في الملاحظة "'''شرح أوسع'''" مثل: | ||
'''شرح أوسع''': اقرأ القسم "[[React/hooks intro#.D8.A7.D9.84.D8.AD.D8.A7.D9.81.D8.B2 .D9.84.D8.A5.D8.B6.D8.A7.D9.81.D8.A9 .D8.A7.D9.84.D8.AE.D8.B7.D8.A7.D9.81.D8.A7.D8.AA|الحافز لإضافة الخطافات]]" لمعرفة سبب إضافة الخطافات إلى React. | '''شرح أوسع''': اقرأ القسم "[[React/hooks intro#.D8.A7.D9.84.D8.AD.D8.A7.D9.81.D8.B2 .D9.84.D8.A5.D8.B6.D8.A7.D9.81.D8.A9 .D8.A7.D9.84.D8.AE.D8.B7.D8.A7.D9.81.D8.A7.D8.AA|الحافز لإضافة الخطافات]]" لمعرفة سبب إضافة الخطافات إلى [[React]]. | ||
إذ تحوي مثل هذه الملاحظة الموجودة في نهاية كل قسم على رابط يحوي شرحًا موسَّعًا يمكن الرجوع إليه. | إذ تحوي مثل هذه الملاحظة الموجودة في نهاية كل قسم على رابط يحوي شرحًا موسَّعًا يمكن الرجوع إليه. | ||
== خطاف الحالة == | == خطاف الحالة == | ||
المثال التالي يصيِّر عدادًا، إذ ستزيد | المثال التالي يصيِّر (render) عدادًا، إذ ستزيد قيمته عند الضغط على زر محدَّد:<syntaxhighlight lang="javascript"> | ||
import React, { useState } from 'react'; | import React, { useState } from 'react'; | ||
function Example() { | function Example() { | ||
// | // "count" التصريح عن متغير حالة جديد ندعوه | ||
const [count, setCount] = useState(0); | const [count, setCount] = useState(0); | ||
سطر 24: | سطر 25: | ||
); | ); | ||
} | } | ||
</syntaxhighlight>في هذه الشيفرة، <code>useState</code> هو خطاف (سنتحدث عن ما الذي يعينه هذا الأمر). نستدعي هذا الخطاف داخل مكون دالة لإضافة بعض الحالات المحلية إليه. ستحافظ React على هذه الحالة بين عمليات إعادة التصيير. يعيد <code>useState</code> زوجًا هو: قيمة الحالة الحالية ودالة تمكنك من تحديثها. يمكنك استدعاء هذه الدالة من معالج حدث أو أي مكان آخر. هي تشبه this.setState في صنف باستثناء | </syntaxhighlight>في هذه الشيفرة، <code>useState</code> هو خطاف (سنتحدث عن ما الذي يعينه هذا الأمر). نستدعي هذا الخطاف داخل مكون دالة لإضافة بعض الحالات المحلية إليه. ستحافظ [[React]] على هذه الحالة بين عمليات إعادة التصيير. يعيد <code>useState</code> زوجًا هو: قيمة الحالة الحالية ودالة تمكنك من تحديثها. يمكنك استدعاء هذه الدالة من معالج حدث أو أي مكان آخر. هي تشبه <code>this.setState</code> في أي صنف باستثناء أنَّها لا تدمج الحالة القديمة مع الحالة الجديدة. (سنوضح الفرق بين <code>useState</code> و <code>this.state</code> عبر مثال عملي في صفحة "[[React/hooks state|استعمال خطاف الحالة]]".) | ||
الوسيط الوحيد الذي يمكنك تمريره إلى useState هو الحالة الأولية. في المثال أعلاه، الحالة الأولية هي 0 | الوسيط الوحيد الذي يمكنك تمريره إلى <code>useState</code> هو الحالة الأولية. في المثال أعلاه، الحالة الأولية هي <code>0</code> لأنَّنا افترضنا وجوب بدء عملية العد من الصفر. لاحظ أنَّه بخلاف <code>this.state</code>، ليس إجباريًّا أن تكون الحالة هنا كائنًا رغم أنَّ تكون كذلك أن أردت أنت ذلك. وسيط الحالة الأولية يستعمل فقط في عملية التصيير الأولى. | ||
=== التصريح عن متغيرات عديدة للحالة === | === التصريح عن متغيرات عديدة للحالة === | ||
سطر 37: | سطر 38: | ||
// ... | // ... | ||
} | } | ||
</syntaxhighlight>تمكننا صيغة تفكيك المصفوفة من إعطاء أسماء مختلفة إلى متغيرات الحالة التي | </syntaxhighlight>تمكننا صيغة تفكيك المصفوفة من إعطاء أسماء مختلفة إلى متغيرات الحالة التي صرَّحنا عنها عبر استدعاء <code>useState</code>. هذه الأسماء ليست جزءًا من الواجهة <code>useState</code> البرمجية، ولكن [[React]] تفترض أنَّك إن استدعيت <code>useState</code> عدة مرات، فإنَّك تفعل ذلك بالترتيب نفسه خلال كل عملية تصيير. سنعود لاحقًا لمناقشة كيفية عمل هذا السلوك ومتى يكون استعماله مفيدًا. | ||
=== ولكن ما هو الخطاف؟ === | === ولكن ما هو الخطاف؟ === | ||
الخطافات هي دوال تمكنك من "تعليق" (hook into) حالة React وميزات دورة الحياة من مكونات الدالة. لا تعمل الخطافات داخل الأصناف، إذ تمكنك من استعمال React دون الحاجة إلى الأصناف. (لا ننصح | الخطافات هي دوال تمكنك من "تعليق" (hook into) حالة [[React]] وميزات دورة الحياة (lifecycle) من مكونات الدالة. لا تعمل الخطافات داخل الأصناف، إذ تمكنك من استعمال [[React]] دون الحاجة إلى الأصناف. (لا ننصح [[React/hooks intro#.D8.AE.D8.B7.D8.A9 .D8.A7.D9.84.D8.A7.D8.B9.D8.AA.D9.85.D8.A7.D8.AF .D8.A7.D9.84.D8.AA.D8.AF.D8.B1.D9.8A.D8.AC.D9.8A|بإعادة كتابة المكونات الحالية الخاصة بك]] بين عشية وضحاها ولكن ننصح ببدء استعمال الخطافات في المكونات الجديدة إن أردت ذلك.) | ||
توفر React عددًا محدودًا من الخطافات المُضمَّنة | توفر [[React]] عددًا محدودًا من الخطافات المُضمَّنة منها <code>useState</code>. يمكنك أيضًا إنشاء الخطافات الخاصة بك لإعادة استعمال سلوك ذي حالة بين مكونات مختلفة. سنتطرق أولًا إلى الخطافات المُضمَّنة في [[React]]. | ||
'''شرح أوسع''': يمكنك تعلم المزيد حول خطاف الحالة في توثيق مخصص به هو "[[React/hooks state|استعمال خطاف الحالة]]". | '''شرح أوسع''': يمكنك تعلم المزيد حول خطاف الحالة في توثيق مخصص به هو "[[React/hooks state|استعمال خطاف الحالة]]". | ||
== خطاف التأثير == | == خطاف التأثير == | ||
من المرجح | من المرجح أنَّك أجريت بعض عمليات جلب البيانات، أو الاشتراكات، أو تغير DOM يدويًا من مكونات [[React]] من قبل. نُطلِق على هذه العمليات بأنَّها عمليات تملك "تأثيرات جانبية" (side effects، أو "تأثيرات" فقط للاختصار) لأنَّها تستطيع أن تؤثر على مكونات أخرى ولا يمكن تنفيذها أثناء عملية التصيير. | ||
خطاف التأثير (Effect Hook) - الذي هو useEffect - يضيف القدرة على تنفيذ تأثيرات جانبية من مكون دالة. إنه يخدم الغرض ذاته الذي يفعله | خطاف التأثير (Effect Hook) - الذي هو <code>[[React/hooks effect|useEffect]]</code> - يضيف القدرة على تنفيذ تأثيرات جانبية من مكون دالة. إنه يخدم الغرض ذاته الذي يفعله <code>componentDidMount</code>، و <code>componentDidUpdate</code>، و <code>componentWillUnmount</code> في أصناف [[React]]، ولكن في واجهة برمجية واحدة. (سنجري عملية موازنة ونوضح الفرق بين <code>useEffect</code> وهذه التوابع مع أمثلة عملية في صفحة "[[React/hooks effect|استعمال خطاف التأثير]]".) | ||
على سبيل المثال، المكون التالي يضبط عنوان الصفحة بعد تحديث React شجرة DOM:<syntaxhighlight lang="javascript"> | على سبيل المثال، المكون التالي يضبط عنوان الصفحة بعد تحديث [[React]] شجرة DOM:<syntaxhighlight lang="javascript"> | ||
import React, { useState, useEffect } from 'react'; | import React, { useState, useEffect } from 'react'; | ||
سطر 72: | سطر 73: | ||
); | ); | ||
} | } | ||
</syntaxhighlight>عند استدعاء | </syntaxhighlight>عند استدعاء <code>useEffect</code>، نخبر بذلك [[React]] بتنفيذ الدالة "<code>effect</code>" الخاصة بك بعد تطبيق التغييرات على الشجرة DOM. يُصرَّح عن التأثيرات داخل المكون، لذا يمكنها الوصول إلى خاصياته (props) وحالته (state). افتراضيًّا، تنفذ [[React]] التأثيرات بعد كل عملية تصيير بما فيها عملية التصيير الأولى. (سنتحدث بالتفصيل عن هذا السلوك مع موازنته مع سلوك دورات حياة صنف في الصفحة "[[React/hooks effect|استعمال خطاف التأثير]]".) | ||
قد تحدِّد التأثيرات اختياريًّا كيفية إجراء عملية "تنظيف" بعد تنفيذها عبر إعادة دالة. على سبيل المثال، يستعمل المكون التالي تأثيرًا للاشتراك بحالة اتصال صديق (friend’s online status) ثم يجري عملية تنظيف عبر إلغاء الاشتراك منها:<syntaxhighlight lang="javascript"> | قد تحدِّد التأثيرات اختياريًّا كيفية إجراء عملية "تنظيف" بعد تنفيذها عبر إعادة دالة. على سبيل المثال، يستعمل المكون التالي تأثيرًا للاشتراك بحالة اتصال صديق (friend’s online status) ثم يجري عملية تنظيف عبر إلغاء الاشتراك منها:<syntaxhighlight lang="javascript"> | ||
سطر 97: | سطر 98: | ||
return isOnline ? 'Online' : 'Offline'; | return isOnline ? 'Online' : 'Offline'; | ||
} | } | ||
</syntaxhighlight>في هذا المثال، ستلغي React الاشتراك من ChatAPI عند فصل (unmount) المكون وقبل إعادة تنفيذ التأثير نتيجة عملية التصيير اللاحقة. (إن أردت، هنالك طريقة لإخبار React بتخطي عملية إعادة الاشتراك إن لم يتغير props.friend.id الذي مررناه إلى ChatAPI.) | </syntaxhighlight>في هذا المثال، ستلغي [[React]] الاشتراك من <code>ChatAPI</code> عند فصل (unmount) المكون وقبل إعادة تنفيذ التأثير نتيجة عملية التصيير اللاحقة. (إن أردت، هنالك طريقة لإخبار [[React]] بتخطي عملية إعادة الاشتراك إن لم يتغير <code>props.friend.id</code> الذي مررناه إلى <code>ChatAPI</code>.) | ||
بشكل مشابه للخطاف | بشكل مشابه للخطاف <code>useState</code>، تستطيع استعمال أكثر من تأثير في مكون:<syntaxhighlight lang="javascript"> | ||
function FriendStatusWithCounter(props) { | function FriendStatusWithCounter(props) { | ||
const [count, setCount] = useState(0); | const [count, setCount] = useState(0); | ||
سطر 118: | سطر 119: | ||
} | } | ||
// ... | // ... | ||
</syntaxhighlight>تسمح لك الخطافات بتنظيم التأثيرات الجانبية في مكون | </syntaxhighlight>تسمح لك الخطافات بتنظيم التأثيرات الجانبية في مكون بناءً على ترابط الأجزاء مع بعضها (مثل إضافة وإزالة اشتراك) عوض التقسيم الإجباري المستند إلى توابع دورة الحياة. | ||
'''شرح أوسع''': يمكن تعلم المزيد حول الخطاف useEffect في صفحة مخصصة به هي "[[React/hooks effect|استعمال خطاف التأثير]]". | '''شرح أوسع''': يمكن تعلم المزيد حول الخطاف <code>useEffect</code> في صفحة مخصصة به هي "[[React/hooks effect|استعمال خطاف التأثير]]". | ||
== قواعد تخص الخطافات == | == قواعد تخص الخطافات == | ||
الخطافات هي دوال في | الخطافات هي دوال في [[JavaScript]]، ولكنها تفرض تطبيق قاعدتين إضافيتين هما: | ||
* | * تُستدعَى الخطافات فقط في المستوى الأعلى (top level). بناءً على ذلك، لا تستدعي الخطافات داخل حلقات تكرارية، أو شروط، أو دوال متشعبة. | ||
* | * تُستدعَى الخطافات فقط من مكونات دالة [[React]] (أي React function components). لا تستدعي الخطافات من دوال [[JavaScript]] العادية. (هنالك مكان آخر صالح يمكن استدعاء الخطافات منه يحدد عند بناء [[React/hooks custom|خطافات مخصصة خاصة بك]]. سنتحدث عن هذا النوع من الخطافات بعد قليل.) | ||
نوفر | نوفر [https://www.npmjs.com/package/eslint-plugin-react-hooks إضافةً لاكتشاف أخطاء الصياغة] يمكنها أن تطبِّق هاتين القاعدتين تلقائيًّا. نتفهَّم أنَّ هاتين القاعدتين قد تبدوان لك شكلًا من أشكال التقيد لسلوك الخطافات أو قد تسببان لك القلق عند بدء استعمال الخطافات، ولكن كن على يقين أنَّهما ضروريتان لعمل الخطافات بشكل صحيح. | ||
'''شرح أوسع''': يمكن قراءة المزيد حول هاتين القاعدتين في صفحة "[[React/hooks rules|قواعد استعمال الخطافات]]". | '''شرح أوسع''': يمكن قراءة المزيد حول هاتين القاعدتين في صفحة "[[React/hooks rules|قواعد استعمال الخطافات]]". | ||
== إنشاء خطافات مخصصة | == إنشاء خطافات مخصصة == | ||
بعض الأحيان، نحتاج إلى إعادة استعمال بعض | بعض الأحيان، نحتاج إلى إعادة استعمال بعض الشيفرات ذات الحالة (stateful logic) بين المكونات. تقليديًّا، يوجد حلان لهذه المشكلة هما: [[React/higher order components|المكونات ذات الترتيب الأعلى]]، و<nowiki/>[[React/render props|خاصيات التصيير]]. تمكنك الخطافات المخصصة من إنجاز هذه المهمة، ولكن دون إضافة المزيد من المكونات إلى شجرتك. | ||
في قسم سابق من هذه الصفحة، | في قسم سابق من هذه الصفحة، عرَّفنا المكون <code>FriendStatus</code> الذي يستدعي الخطاف <code>useState</code> والخطاف <code>useEffect</code> للاشتراك في حالة اتصال صديق. افترض أنَّنا نريد أيضًا إعادة استعمال شيفرة هذا الاشتراك في مكون آخر فماذا نفعل؟ | ||
أولًا، سنستخرج هذا | أولًا، سنستخرج هذا الشيفرة إلى خطاف مخصص يدعى <code>useFriendStatus</code> بالشكل التالي:<syntaxhighlight lang="javascript"> | ||
import React, { useState, useEffect } from 'react'; | import React, { useState, useEffect } from 'react'; | ||
سطر 154: | سطر 155: | ||
return isOnline; | return isOnline; | ||
} | } | ||
</syntaxhighlight>يأخذ الوسيط | </syntaxhighlight>يأخذ الوسيط <code>friendID</code>، ويعيد حالة الصديق أي إن كان متصلًا أم لا. | ||
الآن، يمكننا استعماله من أي مكون نريد:<syntaxhighlight lang="javascript"> | الآن، يمكننا استعماله من أي مكون نريد:<syntaxhighlight lang="javascript"> | ||
سطر 175: | سطر 176: | ||
); | ); | ||
} | } | ||
</syntaxhighlight>حالة هذه المكونات هي مستقلة كليًّا. الخطافات هي وسيلة لإعادة استعمال | </syntaxhighlight>حالة هذه المكونات هي مستقلة كليًّا. الخطافات هي وسيلة لإعادة استعمال الشيفرة ذات الحالة وليس الحالة نفسها. في الحقيقة، كل استدعاء إلى خطاف يملك حالة منعزلة تمامًا، لذا يمكنك حتى استعمال نفس [[React/hooks custom|الخطاف المخصص]] مرتين في مكون واحد. | ||
[[React/hooks custom|الخطافات المخصصة]] هي أقرب للعرف من كونها ميزة. إن بدأ اسم دالة بالكلمة <code>use</code> واستدعت خطافات أخرى، نقول أنَّها "خطاف مخصص". التسمية <code>useSomething</code> المتعارف عليها هي التي تمكن [https://www.npmjs.com/package/eslint-plugin-react-hooks إضافة تصحيح أخطاء الصياغة] (linter plugin) من تنقيح الشيفرة التي تستعمل الخطافات. | |||
يمكنك كتابة [[React/hooks custom|خطافات مخصصة]] تغطي مجالًا واسعًا من الحالات مثل معالجة النماذج، والتحريك، والاشتراكات التصريحية (declarative subscriptions)، والمؤقتات، وغيرها الكثير. نتطلع بشوق لرؤية [[React/hooks custom|الخطافات المخصصة]] التي سيبتكرها المجتمع. | |||
'''شرح أوسع''': يمكنك تعلم المزيد حول الخطافات المخصصة بالتفصيل في صفحة "[[React/hooks custom|بناء خطافات خاصة بك]]". | |||
== خطافات أخرى == | |||
هنالك بعض الخطافات المضمنة غير شائعة الاستخدام يمكن أن تجد فيها فائدةً ما. على سبيل المثال، <code>useContext</code> يسمح لك بالاشتراك بسياق [[React]] دون اللجوء إلى التشعب:<syntaxhighlight lang="javascript"> | |||
function Example() { | |||
const locale = useContext(LocaleContext); | |||
const theme = useContext(ThemeContext); | |||
// ... | |||
} | |||
</syntaxhighlight>والخطاف <code>useReducer</code> يمكنك من إدارة الحالة المحلية للمكونات المعقدة مع مخفِّض (reducer):<syntaxhighlight lang="javascript"> | |||
function Todos() { | |||
const [todos, dispatch] = useReducer(todosReducer); | |||
// ... | |||
</syntaxhighlight>'''شرح أوسع''': يمكنك الاطلاع على جميع الخطافات المضمَّنة في التوثيق "[[React/hooks reference|مرجع إلى الواجهة البرمجية للخطافات]]". | |||
== الخطوات التالية == | |||
كان هذا الشرح مختصرًا ومفيدًا، أليس كذلك؟! إن لم تعتقد ذلك أو كنت تريد تعلم المزيد وبالتفصيل، يمكنك الانتقال إلى الصفحات التالية بدءًا من توثيق "[[React/hooks state|استعمال خطاف الحالة]]". | |||
يمكنك أيضًا في أي وقت الاطلاع على توثيق "[[React/hooks reference|مرجع إلى الواجهة البرمجية للخطافات]]" وصفحة "[[React/hooks faq|الأسئلة الشائعة حول الخطافات]]". | |||
أخيرًا، إن لم تكن قد اطلعت على صفحة "[[React/hooks intro|مدخل إلى الخطافات]]"، فلا تدع فرصة قراءتها تفوتك، إذ تشرح تلك الصفحة سبب إضافة الخطافات وكيفية البدء باستعمالها جنبًا إلى جنب مع الأصناف دون إعادة كتابة تطبيقك. | |||
== انظر أيضًا == | == انظر أيضًا == | ||
* [[React/hooks intro|مدخل إلى الخطافات]] | * [[React/hooks intro|مدخل إلى الخطافات]] | ||
* [[React/hooks state|استعمال خطاف الحالة]] | * [[React/hooks state|استعمال خطاف الحالة]] | ||
* [[React/hooks effect|استعمال خطاف التأثير]] | * [[React/hooks effect|استعمال خطاف التأثير]] | ||
* [[React/hooks rules|قواعد استعمال الخطافات]] | * [[React/hooks rules|قواعد استعمال الخطافات]] | ||
* [[React/hooks custom|بناء | * [[React/hooks custom|بناء خطافات خاصة بك]] | ||
* [[React/hooks reference|مرجع إلى الواجهة البرمجية للخطافات]] | * [[React/hooks reference|مرجع إلى الواجهة البرمجية للخطافات]] | ||
* [[React/hooks faq|الأسئلة الشائعة حول الخطافات]] | * [[React/hooks faq|الأسئلة الشائعة حول الخطافات]] | ||
سطر 189: | سطر 215: | ||
== مصادر== | == مصادر== | ||
*[https://reactjs.org/docs/hooks-overview.html صفحة لمحة خاطفة عن الخطافات في توثيق React الرسمي.] | *[https://reactjs.org/docs/hooks-overview.html صفحة لمحة خاطفة عن الخطافات في توثيق React الرسمي.] | ||
[[تصنيف:React]] | |||
[[تصنيف:React Hooks]] |
المراجعة الحالية بتاريخ 10:58، 6 نوفمبر 2020
الخطافات هي إضافة جديدة إلى الإصدار 16.8 في React، إذ تسمح لك باستعمال ميزة الحالة وميزات React الأخرى دون كتابة أي صنف.
الخطافات متوافقة مع ما سبقها بشكل كامل. توفر هذه الصفحة نظرة عامة وسريعة حول الخطافات لمستخدمي React ذوي الخبرة. إن ازددت حيرةً في بعض المواضع أثناء قراءة هذه الصفحة، فانتقل إلى الرابط المذكور في الملاحظة "شرح أوسع" مثل:
شرح أوسع: اقرأ القسم "الحافز لإضافة الخطافات" لمعرفة سبب إضافة الخطافات إلى React.
إذ تحوي مثل هذه الملاحظة الموجودة في نهاية كل قسم على رابط يحوي شرحًا موسَّعًا يمكن الرجوع إليه.
خطاف الحالة
المثال التالي يصيِّر (render) عدادًا، إذ ستزيد قيمته عند الضغط على زر محدَّد:
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>
);
}
في هذه الشيفرة، useState
هو خطاف (سنتحدث عن ما الذي يعينه هذا الأمر). نستدعي هذا الخطاف داخل مكون دالة لإضافة بعض الحالات المحلية إليه. ستحافظ React على هذه الحالة بين عمليات إعادة التصيير. يعيد useState
زوجًا هو: قيمة الحالة الحالية ودالة تمكنك من تحديثها. يمكنك استدعاء هذه الدالة من معالج حدث أو أي مكان آخر. هي تشبه this.setState
في أي صنف باستثناء أنَّها لا تدمج الحالة القديمة مع الحالة الجديدة. (سنوضح الفرق بين useState
و this.state
عبر مثال عملي في صفحة "استعمال خطاف الحالة".)
الوسيط الوحيد الذي يمكنك تمريره إلى useState
هو الحالة الأولية. في المثال أعلاه، الحالة الأولية هي 0
لأنَّنا افترضنا وجوب بدء عملية العد من الصفر. لاحظ أنَّه بخلاف this.state
، ليس إجباريًّا أن تكون الحالة هنا كائنًا رغم أنَّ تكون كذلك أن أردت أنت ذلك. وسيط الحالة الأولية يستعمل فقط في عملية التصيير الأولى.
التصريح عن متغيرات عديدة للحالة
يمكنك استعمال خطاف الحالة (State Hook) أكثر من مرة مكون واحد بالشكل التالي:
function ExampleWithManyStates() {
// Declare multiple state variables!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}
تمكننا صيغة تفكيك المصفوفة من إعطاء أسماء مختلفة إلى متغيرات الحالة التي صرَّحنا عنها عبر استدعاء useState
. هذه الأسماء ليست جزءًا من الواجهة useState
البرمجية، ولكن React تفترض أنَّك إن استدعيت useState
عدة مرات، فإنَّك تفعل ذلك بالترتيب نفسه خلال كل عملية تصيير. سنعود لاحقًا لمناقشة كيفية عمل هذا السلوك ومتى يكون استعماله مفيدًا.
ولكن ما هو الخطاف؟
الخطافات هي دوال تمكنك من "تعليق" (hook into) حالة React وميزات دورة الحياة (lifecycle) من مكونات الدالة. لا تعمل الخطافات داخل الأصناف، إذ تمكنك من استعمال React دون الحاجة إلى الأصناف. (لا ننصح بإعادة كتابة المكونات الحالية الخاصة بك بين عشية وضحاها ولكن ننصح ببدء استعمال الخطافات في المكونات الجديدة إن أردت ذلك.)
توفر React عددًا محدودًا من الخطافات المُضمَّنة منها useState
. يمكنك أيضًا إنشاء الخطافات الخاصة بك لإعادة استعمال سلوك ذي حالة بين مكونات مختلفة. سنتطرق أولًا إلى الخطافات المُضمَّنة في React.
شرح أوسع: يمكنك تعلم المزيد حول خطاف الحالة في توثيق مخصص به هو "استعمال خطاف الحالة".
خطاف التأثير
من المرجح أنَّك أجريت بعض عمليات جلب البيانات، أو الاشتراكات، أو تغير DOM يدويًا من مكونات React من قبل. نُطلِق على هذه العمليات بأنَّها عمليات تملك "تأثيرات جانبية" (side effects، أو "تأثيرات" فقط للاختصار) لأنَّها تستطيع أن تؤثر على مكونات أخرى ولا يمكن تنفيذها أثناء عملية التصيير.
خطاف التأثير (Effect Hook) - الذي هو useEffect
- يضيف القدرة على تنفيذ تأثيرات جانبية من مكون دالة. إنه يخدم الغرض ذاته الذي يفعله componentDidMount
، و componentDidUpdate
، و componentWillUnmount
في أصناف React، ولكن في واجهة برمجية واحدة. (سنجري عملية موازنة ونوضح الفرق بين useEffect
وهذه التوابع مع أمثلة عملية في صفحة "استعمال خطاف التأثير".)
على سبيل المثال، المكون التالي يضبط عنوان الصفحة بعد تحديث React شجرة DOM:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
عند استدعاء useEffect
، نخبر بذلك React بتنفيذ الدالة "effect
" الخاصة بك بعد تطبيق التغييرات على الشجرة DOM. يُصرَّح عن التأثيرات داخل المكون، لذا يمكنها الوصول إلى خاصياته (props) وحالته (state). افتراضيًّا، تنفذ React التأثيرات بعد كل عملية تصيير بما فيها عملية التصيير الأولى. (سنتحدث بالتفصيل عن هذا السلوك مع موازنته مع سلوك دورات حياة صنف في الصفحة "استعمال خطاف التأثير".)
قد تحدِّد التأثيرات اختياريًّا كيفية إجراء عملية "تنظيف" بعد تنفيذها عبر إعادة دالة. على سبيل المثال، يستعمل المكون التالي تأثيرًا للاشتراك بحالة اتصال صديق (friend’s online status) ثم يجري عملية تنظيف عبر إلغاء الاشتراك منها:
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
في هذا المثال، ستلغي React الاشتراك من ChatAPI
عند فصل (unmount) المكون وقبل إعادة تنفيذ التأثير نتيجة عملية التصيير اللاحقة. (إن أردت، هنالك طريقة لإخبار React بتخطي عملية إعادة الاشتراك إن لم يتغير props.friend.id
الذي مررناه إلى ChatAPI
.)
بشكل مشابه للخطاف useState
، تستطيع استعمال أكثر من تأثير في مكون:
function FriendStatusWithCounter(props) {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
// ...
تسمح لك الخطافات بتنظيم التأثيرات الجانبية في مكون بناءً على ترابط الأجزاء مع بعضها (مثل إضافة وإزالة اشتراك) عوض التقسيم الإجباري المستند إلى توابع دورة الحياة.
شرح أوسع: يمكن تعلم المزيد حول الخطاف useEffect
في صفحة مخصصة به هي "استعمال خطاف التأثير".
قواعد تخص الخطافات
الخطافات هي دوال في JavaScript، ولكنها تفرض تطبيق قاعدتين إضافيتين هما:
- تُستدعَى الخطافات فقط في المستوى الأعلى (top level). بناءً على ذلك، لا تستدعي الخطافات داخل حلقات تكرارية، أو شروط، أو دوال متشعبة.
- تُستدعَى الخطافات فقط من مكونات دالة React (أي React function components). لا تستدعي الخطافات من دوال JavaScript العادية. (هنالك مكان آخر صالح يمكن استدعاء الخطافات منه يحدد عند بناء خطافات مخصصة خاصة بك. سنتحدث عن هذا النوع من الخطافات بعد قليل.)
نوفر إضافةً لاكتشاف أخطاء الصياغة يمكنها أن تطبِّق هاتين القاعدتين تلقائيًّا. نتفهَّم أنَّ هاتين القاعدتين قد تبدوان لك شكلًا من أشكال التقيد لسلوك الخطافات أو قد تسببان لك القلق عند بدء استعمال الخطافات، ولكن كن على يقين أنَّهما ضروريتان لعمل الخطافات بشكل صحيح.
شرح أوسع: يمكن قراءة المزيد حول هاتين القاعدتين في صفحة "قواعد استعمال الخطافات".
إنشاء خطافات مخصصة
بعض الأحيان، نحتاج إلى إعادة استعمال بعض الشيفرات ذات الحالة (stateful logic) بين المكونات. تقليديًّا، يوجد حلان لهذه المشكلة هما: المكونات ذات الترتيب الأعلى، وخاصيات التصيير. تمكنك الخطافات المخصصة من إنجاز هذه المهمة، ولكن دون إضافة المزيد من المكونات إلى شجرتك.
في قسم سابق من هذه الصفحة، عرَّفنا المكون FriendStatus
الذي يستدعي الخطاف useState
والخطاف useEffect
للاشتراك في حالة اتصال صديق. افترض أنَّنا نريد أيضًا إعادة استعمال شيفرة هذا الاشتراك في مكون آخر فماذا نفعل؟
أولًا، سنستخرج هذا الشيفرة إلى خطاف مخصص يدعى useFriendStatus
بالشكل التالي:
import React, { useState, useEffect } from 'react';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
يأخذ الوسيط friendID
، ويعيد حالة الصديق أي إن كان متصلًا أم لا.
الآن، يمكننا استعماله من أي مكون نريد:
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
حالة هذه المكونات هي مستقلة كليًّا. الخطافات هي وسيلة لإعادة استعمال الشيفرة ذات الحالة وليس الحالة نفسها. في الحقيقة، كل استدعاء إلى خطاف يملك حالة منعزلة تمامًا، لذا يمكنك حتى استعمال نفس الخطاف المخصص مرتين في مكون واحد.
الخطافات المخصصة هي أقرب للعرف من كونها ميزة. إن بدأ اسم دالة بالكلمة use
واستدعت خطافات أخرى، نقول أنَّها "خطاف مخصص". التسمية useSomething
المتعارف عليها هي التي تمكن إضافة تصحيح أخطاء الصياغة (linter plugin) من تنقيح الشيفرة التي تستعمل الخطافات.
يمكنك كتابة خطافات مخصصة تغطي مجالًا واسعًا من الحالات مثل معالجة النماذج، والتحريك، والاشتراكات التصريحية (declarative subscriptions)، والمؤقتات، وغيرها الكثير. نتطلع بشوق لرؤية الخطافات المخصصة التي سيبتكرها المجتمع.
شرح أوسع: يمكنك تعلم المزيد حول الخطافات المخصصة بالتفصيل في صفحة "بناء خطافات خاصة بك".
خطافات أخرى
هنالك بعض الخطافات المضمنة غير شائعة الاستخدام يمكن أن تجد فيها فائدةً ما. على سبيل المثال، useContext
يسمح لك بالاشتراك بسياق React دون اللجوء إلى التشعب:
function Example() {
const locale = useContext(LocaleContext);
const theme = useContext(ThemeContext);
// ...
}
والخطاف useReducer
يمكنك من إدارة الحالة المحلية للمكونات المعقدة مع مخفِّض (reducer):
function Todos() {
const [todos, dispatch] = useReducer(todosReducer);
// ...
شرح أوسع: يمكنك الاطلاع على جميع الخطافات المضمَّنة في التوثيق "مرجع إلى الواجهة البرمجية للخطافات".
الخطوات التالية
كان هذا الشرح مختصرًا ومفيدًا، أليس كذلك؟! إن لم تعتقد ذلك أو كنت تريد تعلم المزيد وبالتفصيل، يمكنك الانتقال إلى الصفحات التالية بدءًا من توثيق "استعمال خطاف الحالة".
يمكنك أيضًا في أي وقت الاطلاع على توثيق "مرجع إلى الواجهة البرمجية للخطافات" وصفحة "الأسئلة الشائعة حول الخطافات".
أخيرًا، إن لم تكن قد اطلعت على صفحة "مدخل إلى الخطافات"، فلا تدع فرصة قراءتها تفوتك، إذ تشرح تلك الصفحة سبب إضافة الخطافات وكيفية البدء باستعمالها جنبًا إلى جنب مع الأصناف دون إعادة كتابة تطبيقك.
انظر أيضًا
- مدخل إلى الخطافات
- استعمال خطاف الحالة
- استعمال خطاف التأثير
- قواعد استعمال الخطافات
- بناء خطافات خاصة بك
- مرجع إلى الواجهة البرمجية للخطافات
- الأسئلة الشائعة حول الخطافات