أفضل الممارسات مع خطافات التفاعل
نشرت: 2022-03-10 React Hooks هي إضافة جديدة في React 16.8 تتيح لك استخدام ميزات الحالة وميزات React الأخرى دون كتابة مكون class
. بعبارة أخرى ، الخطافات هي وظائف تتيح لك "ربط" حالة التفاعل وميزات دورة الحياة من مكونات الوظيفة. (لا يعملون داخل مكونات class
).
توفر React بعض الخطافات المدمجة مثل useState
. يمكنك أيضًا إنشاء الخطافات الخاصة بك لإعادة استخدام سلوك الحالة بين المكونات المختلفة. يوضح المثال أدناه عدادًا تُدار حالته باستخدام الخطاف useState()
. في كل مرة تنقر فيها على الزر ، نستخدم setCount()
لتحديث قيمة count
بمقدار 1
.
يعرض هذا المثال عدادًا بقيمة 0
. عند النقر فوق الزر ، فإنه يزيد القيمة بمقدار 1
. يتم تحديد القيمة الأولية للمكون باستخدام useState
.
const [count, setCount] = useState(0)
كما ترى ، قمنا بتعيين ذلك ليكون 0
. ثم نستخدم طريقة onClick()
لاستدعاء setCount
عندما نريد زيادة القيمة.
<button onClick={() => setCount(count + 1)}> Click me </button>
قبل إصدار React Hooks ، كان هذا المثال قد استخدم المزيد من سطور التعليمات البرمجية ، حيث كان علينا الاستفادة من مكون class
.
قواعد رد الفعل هوكس
قبل التعمق في أفضل الممارسات ، نحتاج إلى فهم قواعد React Hooks والتي تعد أيضًا بعض المفاهيم الأساسية للممارسات المقدمة في هذه المقالة.
React Hooks هي وظائف JavaScript ، لكن عليك اتباع قاعدتين عند استخدامها.
- خطاف الاتصال في المستوى الأعلى ؛
- فقط قم باستدعاء الخطافات من مكونات React.
ملاحظة : تم تقديم هاتين القاعدتين في React Hooks ، بدلاً من كونها جزءًا من JavaScript نفسها.
لنلقِ نظرة على هذه القواعد بمزيد من التفصيل.
نداء هوكس على أعلى مستوى
لا تستدعي الخطافات داخل الحلقات أو الشروط أو الوظائف المتداخلة. استخدم الخطافات دائمًا في المستوى العلوي لوظيفة React. باتباع هذه القاعدة ، فإنك تتأكد من استدعاء الخطافات بنفس الترتيب في كل مرة يتم فيها عرض المكون. هذا ما يسمح لـ React بالحفاظ على حالة الخطافات بشكل صحيح بين useState
المتعددة و useEffect
.
لنقم بإنشاء مكون Form
الذي سيكون له حالتان:
-
accountName
-
accountDetail
ستحتوي هذه الحالات على قيم افتراضية ، وسنستخدم خطاف useEffect
الحالة إما في التخزين المحلي لمتصفحنا أو في عنوان وثيقتنا.
الآن ، من المحتمل أن يدير هذا المكون حالته بنجاح إذا ظل كما هو بين الاستدعاءات المتعددة لـ useState
و useEffect
.
function Form() { // 1. Use the accountName state variable const [accountName, setAccountName] = useState('David'); // 2. Use an effect for persisting the form useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); // 3. Use the accountDetail state variable const [accountDetail, setAccountDetail] = useState('Active'); // 4. Use an effect for updating the title useEffect(function updateStatus() { document.title = accountName + ' ' + accountDetail; }); // ... }
إذا تغير ترتيب الخطافات الخاصة بنا (والذي يمكن أن يكون ممكنًا عندما يتم استدعاؤها في حلقات أو شرطية) ، فإن React ستواجه صعوبة في معرفة كيفية الحفاظ على حالة المكون الخاص بنا.
// ------------ useState('David') // 1. Initialize the accountName state variable with 'David' useEffect(persistForm) // 2. Add an effect for persisting the form useState('Active') // 3. Initialize the accountdetail state variable with 'Active' useEffect(updateStatus) // 4. Add an effect for updating the status // ------------- // Second render // ------------- useState('David') // 1. Read the accountName state variable (argument is ignored) useEffect(persistForm) // 2. Replace the effect for persisting the form useState('Active') // 3. Read the accountDetail state variable (argument is ignored) useEffect(updateStatus) // 4. Replace the effect for updating the status // ...
هذا هو الترتيب الذي تتبعه React لاستدعاء الخطافات. نظرًا لأن الترتيب لا يزال كما هو ، فسيكون قادرًا على الحفاظ على حالة المكون الخاص بنا. ولكن ماذا يحدث إذا وضعنا اتصال هوك داخل الشرط؟
// We're breaking the first rule by using a Hook in a condition if (accountName !== '') { useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); }
إن accountName !== ''
true
في أول تصيير ، لذلك نقوم بتشغيل هذا الخطاف. ومع ذلك ، في العرض التالي ، قد يمسح المستخدم النموذج ، مما يجعل الشرط false
. الآن بعد أن تخطينا هذا الخطاف أثناء العرض ، يصبح ترتيب استدعاءات الخطاف مختلفًا:
useState('David') // 1. Read the accountName state variable (argument is ignored) // useEffect(persistForm) // This Hook was skipped! useState('Active') // 2 (but was 3). Fail to read the accountDetails state variable useEffect(updateStatus) // 3 (but was 4). Fail to replace the effect
لن تعرف React ما الذي يجب إرجاعه لاستدعاء useState
Hook الثاني. توقعت React أن استدعاء Hook الثاني في هذا المكون يتوافق مع تأثير persistForm
، تمامًا كما حدث أثناء التصيير السابق - لكنه لم يعد كذلك. من تلك النقطة فصاعدًا ، ستتحول أيضًا كل مكالمة Hook
تالية بعد تلك التي تخطيناها بواحد - مما يؤدي إلى حدوث أخطاء.
هذا هو السبب في أنه يجب استدعاء الخطافات في المستوى الأعلى لمكوناتنا. إذا أردنا تشغيل تأثير بشكل مشروط ، فيمكننا وضع هذا الشرط داخل الخطاف الخاص بنا.
ملاحظة : تحقق من مستندات React Hook لقراءة المزيد عن هذا الموضوع.
فقط استدعاء الخطافات من مكونات التفاعل
لا تستدعي الخطافات من وظائف JavaScript العادية. بدلاً من ذلك ، يمكنك استدعاء الخطافات من مكونات دالة React. دعنا نلقي نظرة على الفرق بين وظيفة JavaScript ومكوِّن React أدناه:
وظيفة JavaScript
import { useState } = "react"; function toCelsius(fahrenheit) { const [name, setName] = useState("David"); return (5/9) * (fahrenheit-32); } document.getElementById("demo").innerHTML = toCelsius;
هنا نستورد الخطاف useState
من حزمة React ، ثم نعلن وظيفتنا. لكن هذا غير صالح لأنه ليس مكونًا من مكونات React.
رد الفعل وظيفة
import React, { useState} from "react"; import ReactDOM from "react-dom"; function Account(props) { const [name, setName] = useState("David"); return <p>Hello, {name}! The price is <b>{props.total}</b> and the total amount is <b>{props.amount}</b></p> } ReactDom.render( <Account total={20} amount={5000} />, document.getElementById('root') );
على الرغم من أن جسم كلاهما يبدو متشابهًا ، فإن الأخير يصبح مكونًا عندما نقوم باستيراد React في الملف. هذا ما يجعل من الممكن لنا استخدام أشياء مثل JSX و React hooks بالداخل.
إذا صادفت استيراد الخطاف المفضل لديك دون استيراد React (مما يجعلها وظيفة عادية) ، فلن تتمكن من الاستفادة من الخطاف الذي قمت باستيراده لأن الخطاف يمكن الوصول إليه فقط في مكون React.
Call Hooks from Custom Hooks
الخطاف المخصص هو وظيفة JavaScript يبدأ اسمها use
ويمكن أن تستدعي الخطافات الأخرى. على سبيل المثال ، يتم استخدام useUserName
أسفل الخطاف المخصص الذي يستدعي useState
و useEffect
. يقوم بجلب البيانات من واجهة برمجة التطبيقات ، وحلقات عبر البيانات ، setIsPresent()
إذا كان اسم المستخدم المحدد الذي استلمه موجودًا في بيانات API.
export default function useUserName(userName) { const [isPresent, setIsPresent] = useState(false); useEffect(() => { const data = MockedApi.fetchData(); data.then((res) => { res.forEach((e) => { if (e.name === userName) { setIsPresent(true); } }); }); }); return isPresent; }
يمكننا بعد ذلك الاستمرار في إعادة استخدام وظيفة هذا الخطاف في أماكن أخرى نحتاج إليها في تطبيقنا. في مثل هذه الأماكن ، باستثناء عند الحاجة ، لن نضطر إلى الاتصال useState
أو useEffect
بعد الآن.
باتباع هذه القاعدة ، فإنك تضمن أن كل المنطق ذي الحالة في أحد المكونات مرئي بوضوح من شفرة المصدر الخاصة به.
البرنامج المساعد ESLint
البرنامج الإضافي ESLint المسمى eslint-plugin-react-hooks
يفرض القواعد المذكورة أعلاه. هذا مفيد في تطبيق القواعد عند العمل في مشروع. أقترح عليك الاستفادة من هذا البرنامج المساعد عند العمل في مشروعك ، خاصة عند العمل مع الآخرين. يمكنك إضافة هذا المكون الإضافي إلى مشروعك إذا كنت ترغب في تجربته:
// Your ESLint configuration { "plugins": [ // ... "react-hooks" ], "rules": { // ... "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies } }
يتم تضمين هذا المكون الإضافي افتراضيًا في Create React App. لذلك لا تحتاج إلى إضافته إذا قمت بتمهيد تطبيقات React باستخدام Create-React-App.
التفكير في هوكس
دعنا نلقي نظرة سريعة على مكونات class
والمكونات الوظيفية (مع الخطافات) ، قبل الغوص في أفضل ممارسات الخطافات القليلة.
إن أبسط طريقة لتعريف مكون في React هي كتابة دالة JavaScript تُرجع عنصر React:
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
يقبل المكون Welcome
props
التي هي كائن يحتوي على بيانات ويعيد عنصر React. يمكننا بعد ذلك استيراد هذا المكون وتقديمه في مكون آخر.
يستخدم مكون class
منهجية برمجة تسمى التغليف والتي تعني أساسًا أن كل ما يتعلق بمكون الفصل سيعيش داخله. توفر طرق دورة الحياة ( constructors
، و componentDidMount()
، render
، وما إلى ذلك) المكونات بنية يمكن التنبؤ بها.
التغليف هو أحد أساسيات OOP ( O bject- O riented P rogramming). يشير إلى تجميع البيانات ضمن الأساليب التي تعمل على تلك البيانات ، ويتم استخدامه لإخفاء قيم أو حالة كائن بيانات منظم داخل فئة - مما يمنع وصول الأطراف غير المصرح لها مباشرة إليها.
مع الخطافات ، يتغير تكوين المكون من كونه مزيجًا من خطافات دورة الحياة - إلى وظائف مع بعض التصيير في النهاية.
مكون الوظيفة
يوضح المثال أدناه كيف يمكن استخدام الخطافات المخصصة في مكون وظيفي (بدون إظهار ماهية الجسم). ومع ذلك ، فإن ما يفعله أو يمكنه فعله غير محدود. قد يكون إنشاء متغيرات الحالة ، واستهلاك السياقات ، واشتراك المكون في تأثيرات جانبية مختلفة - أو كل ما سبق إذا كنت تستخدم خطافًا مخصصًا!
function { useHook{...}; useHook{...}; useHook{...}; return (
...) ؛ }
مكون الفصل
يتطلب منك أحد مكونات class
التوسع من React.Component
وإنشاء دالة render
تقوم بإرجاع عنصر React. يتطلب هذا المزيد من التعليمات البرمجية ولكنه سيمنحك أيضًا بعض الفوائد.
class { constructor(props) {...} componentDidMount() {...} componentWillUnmount() {...} render() {...} }
هناك بعض الفوائد التي تحصل عليها من استخدام المكونات الوظيفية في React:
- سيكون من الأسهل فصل مكونات الحاوية والعروض التقديمية لأنك تحتاج إلى التفكير أكثر في حالة المكون الخاص بك إذا لم يكن لديك وصول إلى
setState()
في المكون الخاص بك. - المكونات الوظيفية أسهل في القراءة والاختبار لأنها وظائف JavaScript عادية بدون حالة أو خطافات لدورة الحياة.
- ينتهي بك الأمر برمز أقل.
- ذكر فريق React أنه قد يكون هناك تعزيز لأداء المكونات الوظيفية في إصدارات React المستقبلية.
يؤدي هذا إلى أول ممارسة أفضل عند استخدام خطافات React.
أفضل ممارسات الخطافات
1. تبسيط الخطافات الخاصة بك
سيمنحك الحفاظ على خطافات React بسيطة القدرة على التحكم والتعامل مع ما يحدث في المكون بشكل فعال طوال حياته. تجنب كتابة الخطافات المخصصة قدر الإمكان ؛ يمكنك useState()
أو useEffect()
بدلاً من إنشاء الخطاف الخاص بك.
إذا وجدت نفسك تستخدم مجموعة من الخطافات المخصصة ذات الصلة بالوظائف ، فيمكنك إنشاء خطاف مخصص يعمل كغلاف لهذه. دعنا نلقي نظرة على مكونين وظيفيين مختلفين مع الخطافات أدناه.
المكون الوظيفي v1.0
function { useHook(...); useHook(...); useHook(...); return( <div>...</div> ); }
المكون الوظيفي v2.0
function { useCustomHook(...); useHook(...); useHook(...); return( <div>...</div> ); }
v2 هو إصدار أفضل لأنه يبقي الخطاف بسيطًا وجميع useHook
الأخرى مضمنة وفقًا لذلك. يتيح لنا ذلك إنشاء وظائف يمكن إعادة استخدامها عبر مكونات مختلفة ، كما يمنحنا مزيدًا من القوة للتحكم في مكوناتنا ومعالجتها بشكل فعال. بدلاً من اعتماد الإصدار 1 الذي تتناثر فيه مكوناتنا بخطافات ، يجب أن تستفيد من الإصدار 2 الذي سيجعل تصحيح الأخطاء أمرًا سهلاً وأنظف الكود الخاص بك.
2. تنظيم وهيكلة الخطافات الخاصة بك
تتمثل إحدى مزايا React Hooks في القدرة على كتابة كود أقل يسهل قراءته. في بعض الحالات ، قد يكون مقدار useEffect()
و useState()
محيرًا. عندما تحافظ على المكون الخاص بك منظمًا ، فسيساعد ذلك في سهولة القراءة والحفاظ على تدفق مكوناتك متسقًا ويمكن التنبؤ به. إذا كانت الخطافات المخصصة الخاصة بك معقدة للغاية ، فيمكنك دائمًا تقسيمها إلى خطافات مخصصة فرعية. استخرج منطق المكون الخاص بك إلى الخطافات المخصصة لجعل شفرتك قابلة للقراءة.
3. استخدم قصاصات خطافات التفاعل
React Hooks Snippets هي امتداد كود Visual Studio لجعل React Hooks أسهل وأسرع. حاليًا ، يتم دعم خمسة خطافات:
-
useState()
-
useEffect()
-
useContext()
-
useCallback()
-
useMemo()
كما تم إضافة مقتطفات أخرى. لقد حاولت العمل مع هذه الخطافات وكانت واحدة من أفضل الممارسات التي استخدمتها شخصيًا أثناء العمل معهم.
هناك طريقتان يمكنك من خلالهما إضافة مقتطفات React Hooks إلى مشروعك:
- أمر
قم بتشغيل VS Code Quick open ( Ctrl + P ) ، الصقext install ALDuncanson.react-hooks-snippets
واضغط على Enter . - ملحق السوق
قم بتشغيل "VS Code Extension Marketplace" ( Ctrl + Shift + X ) وابحث عن "React Hook Snippets". ثم ابحث عن رمز "Alduncanson".
أوصي بالمقتطف الأول. اقرأ المزيد حول المقتطفات هنا أو تحقق من أحدث مقتطفات الخطافات هنا.
4. ضع قواعد الخطافات في الاعتبار
احرص دائمًا على وضع قاعدتي الخطافات التي تعلمناها مسبقًا في الاعتبار أثناء العمل مع React Hooks.
- فقط قم باستدعاء الخطافات الخاصة بك في المستوى الأعلى. لا تستدعي الخطافات داخل الحلقات أو الشروط أو الوظائف المتداخلة.
- استدعِ الخطافات دائمًا من مكونات دالة React أو من الخطافات المخصصة ، لا تستدعي الخطافات من وظائف JavaScript العادية.
يفرض المكون الإضافي ESlint المسمى eslint-plugin-react-hooks
هاتين القاعدتين ، يمكنك إضافة هذا المكون الإضافي إلى مشروعك إذا كنت ترغب في ذلك كما هو موضح أعلاه في قسم قواعد الخطافات.
لم يتم حل أفضل الممارسات بشكل كامل لأن الخطافات لا تزال جديدة نسبيًا. لذلك يجب أن يتم التبني بحذر عند اعتماد أي تقنية مبكرة. مع أخذ ذلك في الاعتبار ، فإن الخطافات هي الطريق لمستقبل React.
خاتمة
وآمل أن يتمتع هذا البرنامج التعليمي. لقد تعلمنا أهم قاعدتين في React Hooks وكيفية التفكير بشكل فعال في الخطافات. نظرنا إلى المكونات الوظيفية وبعض أفضل الممارسات في كتابة الخطافات بالطريقة الصحيحة والفعالة. بقدر ما تكون القواعد موجزة ، من المهم أن تجعلها بوصلة إرشادية لك عند كتابة القواعد. إذا كنت عرضة لنسيانه ، فيمكنك الاستفادة من البرنامج الإضافي ESLint لفرضه.
آمل أن تستوعب جميع الدروس المستفادة هنا في مشروع React القادم. حظ سعيد!
موارد
- "تقديم الخطافات" ، React Docs
- "الوظيفية مقابل مكونات الصنف في التفاعل" ، ديفيد جوش ، متوسط
- "تعتبر Mixins ضارة" ، دان أبراموف ، مدونة React
- "خطافات التفاعل: أفضل الممارسات وتحول في العقلية" ، بريان مانويل ، متوسط
- "React Hooks Snippets For VS Code" ، أنتوني ديفيس ، سوق الكود المرئي