دروس التفاعل: المكونات والخطافات والأداء

نشرت: 2022-03-11

كما أشرنا في الجزء الأول من درس React ، فإن البدء باستخدام React سهل نسبيًا. ابدأ باستخدام Create React App (CRA) ، وابدأ مشروعًا جديدًا ، وابدأ في التطوير. للأسف ، بمرور الوقت ، قد تواجه موقفًا يصعب فيه الحفاظ على شفرتك ، خاصة إذا كنت جديدًا على React. قد تصبح المكونات كبيرة بشكل غير ضروري أو قد ينتهي بك الأمر بعناصر يمكن أن تكون مكونات ولكنها ليست كذلك ، لذلك يمكنك في نهاية المطاف كتابة تعليمات برمجية متكررة هنا وهناك.

هذا هو المكان الذي يجب أن تحاول فيه بدء رحلة React حقًا - من خلال البدء في التفكير في حلول تطوير React.

عندما تقترب من تطبيق جديد ، تصميم جديد تحتاج إلى تحويله إلى تطبيق React لاحقًا ، حاول أولاً تحديد المكونات التي ستكون في رسمك التخطيطي ، وكيف يمكنك فصل المخطط لتسهيل إدارتها ، وأي العناصر ستكون كذلك متكرر (أو سلوكهم على الأقل). حاول تجنب إضافة كود قد يكون "مفيدًا في المستقبل" - قد يكون مغريًا ، لكن هذا المستقبل قد لا يأتي أبدًا وستحتفظ بهذه الوظيفة / المكون العام الإضافي الذي يحتوي على الكثير من الخيارات القابلة للتكوين.

درس React التعليمي: توضيح لمكوّنات React

أيضًا ، إذا كان أحد المكونات أطول من ، دعنا نقول 2-3 ارتفاع نافذة ، فربما يكون من المفيد الفصل (إن أمكن) - حيث سيكون من الأسهل قراءته لاحقًا.

المكونات الخاضعة للرقابة مقابل المكونات غير المتحكم فيها في React

في معظم التطبيقات ، هناك حاجة إلى إدخال وشكل من أشكال التفاعل مع المستخدمين ، مما يسمح لهم بكتابة شيء ما وتحميل ملف واختيار حقل وما إلى ذلك. يتعامل React مع تفاعل المستخدم بطريقتين مختلفتين - المكونات الخاضعة للرقابة وغير المتحكم فيها.

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

 class ControlledInput extends React.Component { state = { value: "" }; onChange = (e) => this.setState({ value: e.target.value }); render() { return ( <input value={this.state.value} onChange={this.onChange}/> ); } }

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

 class UncontrolledInput extends React.Component { input = React.createRef(); getValue = () => { console.log(this.input.current.value); }; render() { return ( <input ref={this.input}/> ); } }

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

الحكام

لقد ذكرنا بالفعل refs ، وهي ميزة خاصة كانت متوفرة في مكونات الفئة حتى ظهور الخطافات في 16.8.

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

للحكام أيضًا ثلاث طرق مختلفة يمكن تحقيقها:

  • باستخدام سلسلة حرفية (موروثة ويجب تجنبها) ،
  • باستخدام وظيفة رد الاتصال التي يتم تعيينها في السمة ref ،
  • من خلال إنشاء المرجع كـ React.createRef() فئة والوصول إليه من خلاله (كن على علم بأن المراجع ستكون متاحة من دورة حياة componentDidMount).

أخيرًا ، هناك حالات لا يتم فيها تمرير المراجع وأوقات تريد فيها الوصول إلى عنصر مرجعي أعمق من المكون الحالي (على سبيل المثال ، لديك مكون <Button> يحتوي على عنصر DOM داخلي <input> والآن أنت موجودة في مكون <Row> ، ومن مكون الصف تريد أن يكون لديك وصول لإدخال وظيفة تركيز DOM. وهذا هو المكان الذي ستستخدم forwardRef ).

إحدى الحالات التي لا يتم فيها تمرير المرجع هي عندما يتم استخدام مكون ذي ترتيب أعلى في أحد المكونات - والسبب مفهوم تمامًا لأن ref ليس prop (مشابه key ) لذلك لا يتم تمريره لذلك أن تشير إلى المكوّن ذو HOC بدلاً من المكون الذي يتم تغليفه به. في مثل هذه الحالة ، يمكننا استخدام React.forwardRef الذي يأخذ الخاصيات والمراجع كوسائط ، والتي يمكن بعد ذلك تخصيصها prop وتمريرها إلى المكون الذي نريد الوصول إليه.

 function withNewReference(Component) { class Hoc extends React.Component { render() { const {forwardedRef, ...props} = this.props; return <Component ref={forwardedRef} {...props}/>; } } return React.forwardRef((props, ref) => { return <Hoc {...props} forwardedRef={ref} />; }); }

حدود الخطأ

كلما زادت الأمور تعقيدًا ، زاد احتمال حدوث خطأ ما. هذا هو السبب في أن حدود الخطأ جزء من React. فكيف يعملون؟

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

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

تعد حدود الخطأ أيضًا مكانًا يمكنك من خلاله إرسال معلومات إلى مسجل الأخطاء الذي تستخدمه (في طريقة دورة حياة componentDidCatch ).

 class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { logToErrorLogger(error, info); } render() { if (this.state.hasError) { return <div>Help, something went wrong.</div>; } return this.props.children; } }

مكونات الترتيب الأعلى

غالبًا ما يتم ذكر مكونات الترتيب الأعلى (HOC) في React وهي نمط شائع جدًا ، من المحتمل أن تستخدمه (أو فعلت ذلك بالفعل). إذا كنت معتادًا على الموجهات ذات الترتيب الأعلى ، فربما تكون قد شاهدت withNavigation, connect, withRouter في العديد من المكتبات.

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

هناك بعض الأشياء التي يمكنك إضافتها ويجب تجنبها:

  • أضف اسم عرض لوظيفة الغلاف HOC (حتى تعرف أنه ، في الواقع ، هو HOC عن طريق تغيير اسم عرض مكون HOC الخاص بك).
  • لا تستخدم HOC داخل طريقة تصيير - يجب أن تستخدم بالفعل مكونًا محسنًا بداخلها ، بدلاً من إنشاء مكون HOC جديد هناك بسبب إعادة تثبيته طوال الوقت وفقدان حالته الحالية.
  • لا يتم نسخ الطرق الثابتة ، لذلك إذا كنت تريد الحصول على بعض الطرق الثابتة داخل المكوّن الإضافي الذي تم إنشاؤه حديثًا ، فأنت بحاجة إلى نسخها بنفسك.
  • لم يتم تمرير المراجع المذكورة ، لذا استخدم React.forwardRef كما هو مذكور سابقًا لحل مثل هذه المشكلات.
 export function importantHoc() { return (Component) => class extends React.Component { importantFunction = () => { console.log("Very Important Function"); }; render() { return ( <Component {...this.props} importantFunction={this.importantFunction} /> ); } }; }

التصميم

لا يرتبط التصميم بالضرورة بـ React نفسها ولكن من الجدير بالذكر لعدة أسباب.

بادئ ذي بدء ، يتم تطبيق أنماط CSS / inline العادية هنا كالمعتاد ويمكنك ببساطة إضافة أسماء فئات من CSS في سمة className ، وستعمل بشكل صحيح. يختلف التصميم المضمن قليلاً عن نمط HTML العادي. لا يتم تمرير السلسلة مع الأنماط بل بالأحرى كائنات ذات قيم صحيحة لكل منها. سمات النمط هي أيضًا من نوع camelCased ، لذا يصبح نصف قطر الحدود borderRadius وما إلى ذلك.

يبدو أن React قد شاع بعض الحلول التي أصبحت شائعة ليس فقط في React ، مثل وحدات CSS التي تم دمجها مؤخرًا في CRA ، حيث يمكنك ببساطة استيراد name.modules.css واستخدام فئاتها مثل الخصائص لتصميم المكون الخاص بك (بعض IDEs ، على سبيل المثال ، WebStorm ، لديها أيضًا ميزة الإكمال التلقائي لذلك ، والتي تخبرك بالأسماء المتاحة).

حل آخر شائع أيضًا في React هو CSS-in-JS (على سبيل المثال ، مكتبة emotion ). فقط للإشارة مرة أخرى ، لا تقتصر وحدات CSS والعواطف (أو CSS-in-JS بشكل عام) على React.

الخطافات في React

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

  • يسمح بإزالة الكثير من مكونات class التي استخدمناها فقط لأننا لم نتمكن من الحصول عليها ، على سبيل المثال ، حالة محلية أو المرجع ، لذلك يبدو أن الكود الخاص بالمكون أسهل في القراءة.
  • يمكّنك من استخدام رمز أقل لنفس التأثير.
  • يجعل التفكير في الوظائف أسهل واختبارها ، على سبيل المثال ، باستخدام مكتبة اختبار التفاعل.
  • يمكن أيضًا أن تأخذ معلمات ، ويمكن بسهولة استخدام نتيجة أحدها بواسطة خطاف آخر (على سبيل المثال ، setState من useState في useEffect ).
  • تصغير طريقة أفضل من الفئات ، والتي تميل إلى أن تكون أكثر إشكالية بعض الشيء لمصغرات.
  • قد يزيل المكوّنات ذات الترتيب الأعلى وتعرض أنماط الدعائم في تطبيقك والتي تسببت في مشاكل جديدة على الرغم من تصميمها لحل مشاكل أخرى.
  • قادرة على أن تكون مصممة خصيصًا من قبل أي مطور React ماهر.

هناك عدد قليل من خطاطيف React المضمنة كوضع افتراضي. الثلاثة الأساسية هي useState و useEffect و useContext . هناك أيضًا العديد من العناصر الإضافية ، على سبيل المثال ، useRef و useMemo ، ولكن في الوقت الحالي ، سنركز على الأساسيات.

لنلقِ نظرة على useState ، ولنستخدمها لإنشاء مثال لعداد مباشر. كيف يعمل؟ حسنًا ، في الأساس ، يكون البناء بأكمله مباشرًا حقًا ويبدو كما يلي:

 export function Counter() { const [counter, setCounter] = React.useState(0); return ( <div> {counter} <button onClick={() => setCounter(counter + 1)}>+</button> </div> ); };

يتم استدعاؤه مع initialState (القيمة) وإرجاع مصفوفة تحتوي على عنصرين معها. بفضل مهمة إتلاف المصفوفات ، يمكننا تعيين المتغيرات لهذه العناصر على الفور. الحالة الأولى هي دائمًا الحالة الأخيرة بعد التحديثات ، في حين أن الحالة الأخرى هي وظيفة سنستخدمها لتحديث القيمة. يبدو سهلاً إلى حد ما ، أليس كذلك؟

أيضًا ، نظرًا لحقيقة أن هذه المكونات كانت تسمى مكونات وظيفية عديمة الحالة ، فإن هذا الاسم لم يعد مناسبًا بعد الآن ، لأنه يمكن أن يكون لها حالة كما هو موضح أعلاه. ومن ثم ، فإن مكونات فئة الأسماء ومكونات الوظيفة تبدو أكثر انسجاما مع ما تفعله بالفعل ، على الأقل من 16.8.0.

يمكن أيضًا استخدام وظيفة التحديث (في حالتنا setCounter ) كدالة تأخذ القيمة السابقة كوسيطة بالشكل التالي:

 <button onClick={() => setCounter(prevCounter => prevCounter + 1)}>+</button> <button onClick={() => setCounter(prevCounter => prevCounter - 1)}>-</button>

ومع ذلك ، على عكس مكون فئة this.setState الذي كان يقوم بدمج ضحل ، فإن تعيين الوظيفة ( setCounter في حالتنا) يتجاوز الحالة بأكملها بدلاً من ذلك.

بالإضافة إلى ذلك ، يمكن أن تكون initialState أيضًا دالة ، وليست مجرد قيمة عادية. هذا له فوائده الخاصة ، حيث سيتم تشغيل هذه الوظيفة فقط أثناء العرض الأولي للمكون وبعد ذلك ، لن يتم استدعاؤها بعد الآن.

 const [counter, setCounter] = useState(() => calculateComplexInitialValue());

أخيرًا ، إذا كنا سنستخدم setCounter بنفس القيمة بالضبط التي كانت لدينا في نفس اللحظة في الحالة الحالية ( counter ) ، فلن يتم عرض المكون.

من ناحية أخرى ، يتعلق الأمر useEffect بإضافة تأثيرات جانبية إلى مكوننا الوظيفي ، سواء كان ذلك اشتراكات ، أو مكالمات API ، أو مؤقتات ، أو أي شيء قد نجده مفيدًا. سيتم تشغيل أي دالة سنمررها إلى useEffect بعد التصيير ، وستقوم بذلك بعد كل عملية تصيير ما لم نضيف قيودًا بشأن تغييرات الخصائص التي يجب إعادة تشغيلها كوسيطة ثانية للدالة. إذا أردنا تشغيله فقط على التركيب والتنظيف عند عدم التحميل ، فسنحتاج فقط إلى تمرير مصفوفة فارغة فيه.

 const fetchApi = async () => { const value = await fetch("https://jsonplaceholder.typicode.com/todos/1"); console.log(await value.json()); }; export function Counter() { const [counter, setCounter] = useState(0); useEffect(() => { fetchApi(); }, []); return ( <div> {counter} <button onClick={() => setCounter(prevCounter => prevCounter + 1)}>+</button> <button onClick={() => setCounter(prevCounter => prevCounter - 1)}>-</button> </div> ); };

سيتم تشغيل الكود أعلاه مرة واحدة فقط بسبب مصفوفة فارغة كوسيطة ثانية. في الأساس ، إنه شيء مثل componentDidMount في مثل هذه الحالة ، لكنه ينطلق لاحقًا. إذا كنت ترغب في الحصول على خطاف مشابه يتم استدعاؤه قبل رسم المتصفح ، فاستخدم useLayoutEffect ، ولكن سيتم تطبيق هذه التحديثات بشكل متزامن ، على عكس useEffect .

يبدو أن useContext هو الأسهل للفهم ، حيث يوفر لنا السياق الذي نريد الوصول إليه (كائن تم إرجاعه بواسطة وظيفة createContext ) وفي المقابل ، فإنه يوفر لنا قيمة هذا السياق.

 const context = useContext(Context);

أخيرًا ، لكتابة الخطاف الخاص بك ، يمكنك فقط كتابة شيء مثل ما يلي:

 function useWindowWidth() { let [windowWidth, setWindowWidth] = useState(window.innerWidth); function handleResize() { setWindowWidth(window.innerWidth); } useEffect(() => { window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return windowWidth; }

في الأساس ، نحن نستخدم خطاف useState المعتاد الذي نخصصه لعرض نافذة القيمة الأولية. ثم في useEffect, نقوم بإضافة مستمع يقوم بتشغيل handleResize عند تغيير حجم كل نافذة. نوضح أيضًا أنه سيتم إلغاء تثبيت المكون (انظر إلى العائد في useEffect ). سهل؟

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

التحقق من الأنواع

كان لدى React فحص خاص بها ، قبل أن يكون Flow و TypeScript خيارًا.

يتحقق PropTypes مما إذا كانت الخصائص (props) التي يتلقاها مكون React وتتحقق مما إذا كانت متوافقة مع ما لدينا. في حالة حدوث موقف مختلف (على سبيل المثال ، كائن بدلاً من مصفوفة) ، فسنحصل على تحذير في وحدة التحكم. من المهم ملاحظة أن PropTypes يتم فحصها فقط في وضع التطوير نظرًا لتأثيرها على الأداء وتحذير وحدة التحكم المذكور أعلاه.

اعتبارًا من React 15.5 ، توجد PropTypes في حزمة مختلفة يجب تثبيتها بشكل منفصل. يتم الإعلان عنها على طول الخصائص في خاصية ثابتة تسمى propTypes (مفاجأة) ، defaultProps مع العناصر الافتراضية التي يتم استخدامها إذا كانت الخصائص غير محددة (الحالة الوحيدة هي الحالة غير المعرفة). لا تتعلق العناصر الافتراضية بـ PropTypes ، ولكن يمكنها حل بعض التحذيرات التي قد تظهر بسبب PropTypes.

الخياران الآخران هما Flow و TypeScript ، وهما أكثر شيوعًا في الوقت الحاضر (خاصة TypeScript).

  • TypeScript عبارة عن مجموعة شاملة مكتوبة من JavaScript ، طورتها Microsoft ، يمكنها التحقق من الأخطاء قبل تشغيل التطبيق ، وتوفر وظائف الإكمال التلقائي الفائقة للتطوير. كما أنه يحسن إعادة البناء بشكل كبير. نظرًا لدعم Microsoft ، الذي يتمتع بخبرة واسعة في اللغات المكتوبة ، فهو خيار آمن أيضًا.
  • Flow ليست لغة ، على عكس TypeScript. إنه مدقق نوع ثابت لجافا سكريبت ، لذا فهو أقرب إلى أداة تقوم بتضمينها في جافا سكريبت منه إلى لغة. الفكرة الكاملة وراء Flow مشابهة تمامًا لما تقدمه TypeScript. يسمح لك بإضافة أنواع لذلك فمن غير المرجح أن يكون لديك أي أخطاء قبل تشغيل الكود. تمامًا مثل TypeScript ، أصبح Flow مدعومًا الآن في CRA (إنشاء تطبيق React) من البداية.

أنا شخصياً أجد TypeScript أسرع (لحظية عملياً) ، خاصة في الإكمال التلقائي ، والذي يبدو أبطأ قليلاً مع Flow. تجدر الإشارة إلى أن IDEs مثل WebStorm ، التي أستخدمها شخصيًا ، تستخدم CLI للتكامل مع Flow. ومع ذلك ، يبدو أنه من الأسهل دمج الاستخدام الاختياري في الملفات ، حيث يمكنك ببساطة إضافة // @flow في بداية الملف لبدء فحص النوع. أيضًا ، مما يمكنني قوله ، يبدو أن TypeScript قد فازت في المعركة مقابل Flow في النهاية - إنها أكثر شيوعًا الآن ، وبعض المكتبات الأكثر شيوعًا يتم إعادة بنائها من Flow إلى TypeScript.

هناك عدد قليل من الخيارات ، المذكورة أيضًا في الوثائق الرسمية ، مثل Reason (تم تطويره بواسطة Facebook واكتسب شعبية في مجتمع React) ، Kotlin (لغة طورتها JetBrains) والمزيد.

من الواضح ، بالنسبة لمطوري الواجهة الأمامية ، أن أسهل طريقة هي القفز والبدء في استخدام Flow و TypeScript ، بدلاً من التبديل إلى Kotlin أو F #. ومع ذلك ، بالنسبة لمطوري الواجهة الخلفية الذين ينتقلون إلى الواجهة الأمامية ، فقد يكون من الأسهل البدء بهم.

أداء الإنتاج ورد الفعل

التغيير الأساسي والأكثر وضوحًا الذي يتعين عليك القيام به لوضع الإنتاج هو التبديل إلى "الإنتاج" لـ DefinePlugin وإضافة UglifyJsPlugin في حالة Webpack. في حالة CRA ، يكون الأمر بسيطًا مثل استخدام npm run build (والذي سيُشغّل react-scripts build التفاعلية). اعلم أن Webpack و CRA ليسا الخيارين الوحيدين ، حيث يمكنك استخدام أدوات إنشاء أخرى مثل Brunch. عادة ما يتم تغطية هذا في الوثائق الرسمية ، سواء كانت وثائق أو وثائق React الرسمية لأداة معينة. للتأكد من ضبط الوضع بشكل صحيح ، يمكنك استخدام أدوات مطور React ، والتي ستمنحك إشارة إلى نوع البناء الذي تستخدمه (الإنتاج مقابل التطوير). ستعمل الخطوات المذكورة أعلاه على تشغيل تطبيقك بدون فحوصات وتحذيرات تأتي من React وسيتم تصغير الحزمة نفسها أيضًا.

هناك بعض الأشياء الأخرى التي يمكنك القيام بها لتطبيق React الخاص بك. ماذا تفعل بملف JS الذي تم إنشاؤه؟ يمكنك البدء بـ "bundle.js" فقط إذا كان الحجم صغيرًا نسبيًا ، أو ربما تفعل شيئًا مثل "المورد + الحزمة" أو ربما "البائع + أصغر جزء مطلوب + استيراد الأشياء عند الحاجة". يكون هذا مفيدًا عندما تتعامل مع تطبيق كبير جدًا ولا تحتاج إلى استيراد كل شيء في البداية. اعلم أن تجميع بعض أكواد JavaScript في الحزمة الرئيسية التي لم يتم استخدامها سيؤدي ببساطة إلى زيادة حجم الحزمة وجعل تحميل التطبيق أبطأ في البداية.

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

تقسيم الكود

يمكن أن يظهر تقسيم الكود بأكثر مما هو مقترح هنا ، لكن دعنا نركز على ما هو متاح لدينا في CRA و React نفسها. بشكل أساسي ، من أجل تقسيم الكود إلى أجزاء مختلفة ، يمكننا استخدام import() الذي يعمل بفضل Webpack ( import نفسه هو اقتراح في المرحلة 3 حتى الآن ، لذلك فهو ليس جزءًا من معيار اللغة حتى الآن). عندما يرى Webpack import ، سيعرف أنه يحتاج إلى بدء تقسيم الكود في هذه المرحلة ولا يمكنه تضمينه في الحزمة الرئيسية (الكود الموجود داخل الاستيراد).

يمكننا الآن توصيله بـ React.lazy() الذي يتطلب import() بمسار ملف يحتوي على المكون الذي يجب تقديمه في ذلك المكان. بعد ذلك ، يمكننا استخدام React.suspense() والذي سيعرض مكونًا مختلفًا في ذلك المكان حتى يتم تحميل المكون المستورد. قد يتساءل المرء. إذا كنا نستورد مكونًا واحدًا ، فلماذا نحتاج إليه؟

هذا ليس هو الحال تمامًا ، حيث React.lazy() المكون الذي نستورده ( import() ، لكن import() قد يجلب جزءًا أكبر من ذلك المكون الفردي. على سبيل المثال ، قد يحتوي هذا المكون المعين على مكتبات أخرى مجمعة ، والمزيد من التعليمات البرمجية ، وما إلى ذلك ، لذا فإن ملفًا واحدًا ليس ضروريًا - فقد يكون هناك العديد من الملفات المجمعة معًا. أخيرًا ، يمكننا التفاف كل ذلك في ErrorBoundary (يمكنك العثور على الكود في قسمنا الخاص بحدود الخطأ) والذي سيكون بمثابة احتياطي إذا فشل شيء ما مع المكون الذي أردنا استيراده (على سبيل المثال ، إذا كان هناك خطأ في الشبكة).

 import ErrorBoundary from './ErrorBoundary'; const ComponentOne = React.lazy(() => import('./ComponentOne')); function MyComponent() { return ( <ErrorBoundary> <React.Suspense fallback={<div>Loading...</div>}> <ComponentOne/> </React.Suspense> </ErrorBoundary> ); }

هذا مثال أساسي ، ولكن من الواضح أنه يمكنك فعل المزيد. يمكنك استخدام import و React.lazy لتقسيم المسار الديناميكي (على سبيل المثال ، المسؤول مقابل المستخدم العادي ، أو فقط المسارات الكبيرة التي تجلب الكثير). اعلم أن React.lazy يدعم فقط عمليات التصدير الافتراضية اعتبارًا من الآن ولا يدعم العرض من جانب الخادم.

رد فعل كود الأداء

فيما يتعلق بالأداء ، إذا كان تطبيق React الخاص بك بطيئًا ، فهناك أداتان يمكن أن تساعدك في اكتشاف المشكلة.

الأول هو علامة تبويب أداء Chrome ، والذي سيخبرك بما يحدث مع كل مكون (على سبيل المثال ، تحميل ، تحديث). بفضل ذلك ، يجب أن تكون قادرًا على تحديد المكون الذي يعرض مشكلات في الأداء ثم تحسينه.

الخيار الآخر هو استخدام DevTools Profiler الذي أصبح متاحًا في React 16.5+ ، وبالتعاون من shouldComponentUpdate (أو PureComponent ، الذي تم شرحه في الجزء الأول من هذا البرنامج التعليمي) ، يمكننا تحسين الأداء لبعض المكونات الهامة.

من الواضح أن استخدام أفضل الممارسات الأساسية للويب هو الأمثل ، مثل إلغاء بعض الأحداث (على سبيل المثال ، التمرير) ، توخي الحذر مع الرسوم المتحركة (باستخدام التحويل بدلاً من تغيير الارتفاع وتحريكه) وما إلى ذلك. يمكن التغاضي عن استخدام أفضل الممارسات بسهولة شديدة ، خاصة إذا كنت ستتعامل مع React للتو.

حالة التفاعل في عام 2019 وما بعده

إذا كنا سنناقش مستقبل React ، شخصيًا ، فلن أكون قلقًا للغاية. من وجهة نظري ، لن تواجه React مشكلة في الحفاظ على عرشها في عام 2019 وما بعده.

تتمتع React بمكانة قوية ، مدعومة من قبل مجتمع كبير من المتابعين ، بحيث سيكون من الصعب التخلص منها. مجتمع React رائع ، ولا ينفد من الأفكار ، ويعمل الفريق الأساسي باستمرار على تحسين React ، وإضافة ميزات جديدة وإصلاح المشكلات القديمة. React مدعومة أيضًا من قبل شركة ضخمة ، لكن مشاكل الترخيص قد ولت - لقد تم ترخيص MIT الآن.

نعم ، هناك بعض الأشياء التي يُتوقع تغييرها أو تحسينها ؛ على سبيل المثال ، جعل React أصغر قليلاً (أحد الإجراءات المذكورة هو إزالة الأحداث الاصطناعية) أو إعادة تسمية className إلى class. بالطبع ، حتى هذه التغييرات التي تبدو طفيفة قد تتسبب في حدوث مشكلات مثل التأثير على توافق المتصفح. أنا شخصياً أتساءل أيضًا عما سيحدث عندما يكتسب WebComponent المزيد من الشعبية ، لأنه قد يزيد من بعض الأشياء التي غالبًا ما تستخدم React مع اليوم. لا أعتقد أنهما سيكونان بديلاً صريحًا ، لكنني أعتقد أنهما قد يكملان بعضهما البعض بشكل جيد.

أما بالنسبة للمدى القصير ، فقد ظهرت الخطافات في React للتو. ربما يكون هذا أكبر تغيير منذ أن حدثت إعادة الكتابة في React ، لأنها ستفتح الكثير من الاحتمالات وتعزز المزيد من مكونات الوظيفة (ويتم تضخيمها بالفعل الآن).

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

هناك الكثير لنتطلع إليه في نظام React البيئي ، ولكن تحديثات الخطافات (و React Native إذا كان شخص ما يحب الهواتف المحمولة) هي على الأرجح أهم التغييرات التي سنراها في عام 2019.

ذات صلة: جلب البيانات التي لا معنى لها أثناء إعادة التحقق من صحة البيانات باستخدام خطافات React: دليل