
تعد أفضل الممارسات التي تتصدر "رد الفعل" أفضل ممارسات منصوص عليها في رد الفعل وحزمة ، والتي توفر تقنيات لزيادة الأداء بالإضافة إلى الأدوات المساعدة لزيادة أداء التطبيق
يجب أن تستخدم لماذا----يجري أن يخطرتك حول إعادة التجنيد التي يمكن تجنبها.
import React from 'react' ;
const useWDYR = __DEV__ ;
if ( useWDYR ) {
const whyDidYouRender = require ( '@welldone-software/why-did-you-render' ) ;
whyDidYouRender ( React , {
// Enable tracking in all pure components by default
trackAllPureComponents : true ,
trackHooks : true ,
include : [
// Uncomment to enable tracking in all components. Must also uncomment /^Screen/ in exclude.
// /.*/,
// Uncomment to enable tracking by displayName, e.g.:
// /^Components/,
] ,
exclude : [
// Uncomment to enable tracking in all components
// /^Components/,
] ,
} ) ;
} استيراد رمز الملف أعلاه في index.js
يتيح لك تخطي إعادة تقديم مكون عندما لا تتغير الدعائم.
من المهم أن تقوم بتذكر الحسابات الثقيلة وكذلك المصفوفات وإبداعات الكائنات حتى لا يتم إعادة إنشاءها على كل عرض. يحدث إعادة تقديم عند تغيير الحالة ، يقوم Redux بإرسال بعض الإجراءات ، أو عندما يكتب المستخدمون في إدخال نص (إعادة تقديم لكل مكبس مفتاح واحد). لا ترغب في تشغيل الكثير من العمليات في تلك التقدم لأسباب واضحة للغاية - لذلك لا يوجد تصفية ثقيلة ، لا توجد عمليات قائمة ، إلخ.
لا يعيد المكون النقي (أو مكون React.memo ) إعادة تقديمه إذا كانت الدعائم متساوية .
سيتم إعادة تخصيص كل متغير تقوم بإنشائه في وظيفة العرض الخاصة بك على كل عرض. على الرغم من أن هذه ليست مشكلة لأنواع القيمة ، فإن هذا يتسبب في اختلاف أنواع المراجع في كل عرض. عندما تمر هذه المتغيرات وصولاً إلى مكونات نقية عبر الدعائم ، فإنها ستظل إعادة تقديم العناء على الرغم من أن الدعائم هي نفسها منطقيا. في كثير من الأحيان هذه المتغيرات تتجاوز الجسر وتجعل تطبيقك بطيئًا.
عندما يعيد تقديم مكونات نقية ، فإنه يقارن الدعائم السابقة بالدعائم الحالية والتحقق مما إذا كانت ضحلة مساواة .
الأرقام والسلاسل والملاءات المنطقية هي أنواع القيمة ، مما يعني أنه يمكن مقارنته بالقيمة :
const i1 = 7 ;
const i2 = 7 ;
const equal = i1 === i2 ; // trueالكائنات والمصفوفات والوظائف هي أنواع مرجعية ، مما يعني أنه لا يمكن مقارنته من خلال قيمتها المنطقية ، ولكن يجب مقارنتها بالرجوع إليها :
const o1 = { x : 7 } ;
const o2 = { x : 7 } ;
const equal = o1 === o2 ; // false المقارنات المرجعية ببساطة تقارن عنوان ذاكرة المتغير ، لذلك فقط o1 === o1 سيكون true في مثال الكود أعلاه.
'isequal
fromأفضل الممارسات الأصلية "لمقارنة الكائنات بالمساواة الفعلية ، ولكن هذا لم يعد مساواة ضحلة بعد الآن.
إذا قمت بإنشاء كائنات في وظيفة العرض الخاصة بك ، فسيتم إعادة إنشاءها على كل عرض واحد. هذا يعني عند إنشاء كائن في العرض الأول ، فهو غير مساواة في الكائن في العرض الثاني. لهذا السبب بالذات ، يوجد المذكرة.
useMemo لتنسيق المصفوفات والكائنات التي ستحافظ على المساواة المرجعية (ولن يتم إعادة إنشاءها على كل عرض) طالما تبقى التبعيات (الوسيطة الثانية) كما هي. استخدم أيضًا useMemo لتخزين الحسابات الثقيلة ، مثل عمليات الصفيف ، والتصفية ، إلخ.useCallback لتذكير وظيفة.useDeepEffect و useDeepCallback و useDeepImperativeHandle و useDeepLayoutEffect من import {useDeepEffect, ...} from 'react-native-best-practice'بشكل عام ، يمكن تحسين مكونات الوظائف بسهولة أكبر بسبب مفهوم السنانير. ومع ذلك ، يمكنك تطبيق تقنيات مماثلة لمكونات الفصل ، فقط كن على علم بأن هذا سيؤدي إلى مزيد من التعليمات البرمجية.
على الرغم من أن الرسوم المتحركة والمهام المكثفة للأداء يتم جدولةها على المواضيع الأصلية ، إلا أن منطق العمل بالكامل يعمل على موضوع JavaScript واحد ، لذا تأكد من قيامك بأقل قدر ممكن من العمل هناك. يمكن مقارنة الكثير من العمل على مؤشر ترابط JavaScript بألعاب عالية في لعبة فيديو - لا يزال بإمكانك النظر حولها بسلاسة ، لكن لا يمكنك تشغيل اللعبة حقًا لأن كل تفاعل يستغرق وقتًا طويلاً.
المكونات الأصلية ( <View> ، <Text> ، <Image> ، <Blurhash> ، ...) يجب أن تمرر الدعائم إلى الأم عبر الجسر. يمكن أن تكون مذكرات ، لذلك React يقارن الدعائم للمساواة الضحلة وتمررها فقط على الجسر إذا كانت مختلفة عن الدعائم من العرض الأخير. إذا لم تقم بتذكير بشكل صحيح ، فقد تقوم بتمرير الدعائم فوق الجسر لكل عرض واحد ، مما يتسبب في احتلال الجسر للغاية. شاهد مثال الأنماط - سيتم إرسال الأنماط عبر الجسر على كل إعادة تقديم!
فيما يلي بعض الأمثلة لمساعدتك على تجنب القيام بالكثير من العمل على موضوع JavaScript الخاص بك:
return < View style = { [ styles . container , { backgroundColor : 'red' } ] } /> ; const style = useMemo ( ( ) => [ styles . container , { backgroundColor : 'red' } ] , [ ] ) ;
return < View style = { style } /> ;useAnimatedStyle ، حيث يجب أن تكون تلك ديناميكية. سيقوم استخدام filter أو map أو عمليات الصفيف الأخرى في العارضين تشغيل العملية بأكملها مرة أخرى لكل عرض.
return (
< Text > { users . filter ( ( u ) => u . status === 'online' ) . length } users online </ Text >
) ; const onlineCount = useMemo (
( ) => users . filter ( ( u ) => u . status === 'online' ) . length ,
[ users ]
) ;
return < Text > { onlineCount } users online </ Text > ; يمكنك أيضًا تطبيق هذا لتقديم طرق عرض رد فعل متعددة باستخدام .map . يمكن أن تكون هذه مذكرات مع useMemo أيضا.
return < View onLayout = { ( layout ) => console . log ( layout ) } /> ; const onLayout = useCallback ( ( layout ) => {
console . log ( layout ) ;
} , [ ] ) ;
return < View onLayout = { onLayout } /> ; تأكد أيضًا من التفكير في المكالمات الأخرى في العارض ، EG useSelector ، useComponentDidAppear - لف رد الاتصال هناك أيضًا!
function MyComponent ( props ) {
return < PressableOpacity onPress = { ( ) => props . logoutUser ( ) } /> ;
} function MyComponent ( props ) {
return < PressableOpacity onPress = { props . logoutUser } /> ;
} function MyComponent ( props ) {
return (
< RecyclerListView scrollViewProps = { { horizontal : props . isHorizontal } } />
) ;
} function MyComponent ( props ) {
const scrollViewProps = useMemo (
( ) => ( {
horizontal : props . isHorizontal ,
} ) ,
[ props . isHorizontal ]
) ;
return < RecyclerListView scrollViewProps = { scrollViewProps } /> ;
} function MyComponent ( ) {
return < RecyclerListView scrollViewProps = { { horizontal : true } } /> ;
} const SCROLL_VIEW_PROPS = { horizontal : true } ;
function MyComponent ( ) {
return < RecyclerListView scrollViewProps = { SCROLL_VIEW_PROPS } /> ;
} ينطبق هذا على الكائنات وكذلك الوظائف التي لا تعتمد على حالة المكون أو الدعائم. استخدم هذا دائمًا إذا استطعت ، لأنه أكثر كفاءة من useMemo و useCallback .
const [ me , setMe ] = useState ( users . find ( ( u ) => u . id === myUserId ) ) ; const [ me , setMe ] = useState ( ( ) => users . find ( ( u ) => u . id === myUserId ) ) ; يقبل خطاف useState وظيفة التهيئة. بينما يدير المثال الأول ("BAD") .find على كل عرض ، فإن المثال الثاني يدير الوظيفة التي تم تمريرها مرة واحدة فقط لتهيئة الحالة.
عند كتابة مكونات جديدة ، وضعت دائمًا عبارة سجل في وظيفة العرض الخاصة بي لمشاهدة عدد المرات التي يعيد فيها مكونات مكوني أثناء العمل عليها. بشكل عام ، يجب إعادة تقديم المكونات بأقل قدر ممكن ، وإذا رأيت الكثير من السجلات التي تظهر في وحدة التحكم الخاصة بي ، فأنا أعلم أنني فعلت شيئًا خاطئًا. إنها ميزة جيدة لوضع هذه الوظيفة في المكون بمجرد البدء في العمل عليها ، وإزالتها بمجرد الانتهاء.
function ComponentImWorkingOn ( ) {
// code
console . log ( 're-rendering ComponentImWorkingOn!' ) ;
return < View /> ;
}يمكنك أيضًا استخدام مكتبة Why-Did-You-Render لمعرفة سبب إعادة عرض المكون (تغييرات الدعامة ، وتغييرات الحالة ، ...) وربما الالتقاط الأخطاء في وقت مبكر.
React.memo export const MyComponent = ( props ) => {
return ...
} const MyComponentImpl = ( props ) => {
return ...
}
export const MyComponent = React . memo ( MyComponentImpl ) ; إذا قام المكون بإعداد نفس النتيجة بالنظر إلى نفس الدعائم ، فيمكنك لفها في مكالمة إلى React.memo(...) . هذا يعني أن React سوف تخطي تقديم المكون ، وإعادة استخدام النتيجة الأخيرة المقدمة. انظر المستندات الرسمية لـ React.memo ، واستخدم React.memo(...) بحكمة.
إذا كان تطبيقك بطيئًا ، فجرّب مكتبة React-Native-Performance و Plipper Plugin لتوضيح أداء التطبيق الخاص بك في جوانب مختلفة مثل الوقت لوقت عرض المكون التفاعلي وتنفيذ البرنامج النصي والمزيد.
لا تتحسن قبل الأوان. بعض الأمثلة المستخدمة هنا (على سبيل المثال useMemo One) صغيرة جدًا وتُظهر الفكرة فقط. يأتي خطاف مثل `USEMEMO أيضًا بتكلفة (تخصيص الوظيفة ومصفوفة DEPS ، ودعا الخطاف الفعلي وتشغيل مقارنة الصفيف) ، لذلك ضع في اعتبارك أنه من الأفضل أن يتم نقلها في الكائنات أو المصفوفات مباشرةً إذا تم تحسين المكون نفسه. بعد تعقيد مكون معين أو مع رسم بياني معين للاعتماد ، يمكن أن تكون وظائف المذكرة بمثابة فوز كبير في الأداء ، ولكن هناك أيضًا حالات تؤدي فيها إلى رمز معقد بشكل غير ضروري وأحيانًا أسوأ. دائما القياس قبل وبعد!
npm i react-native-best-practice
جميع الحجج التي تمر كما في React Hooks الأصلي مثل
import {useDeepEffect} from 'react-native-best-practice'
useDeepEffect(()=>{
},[recreatedDeepObject])
useDeepEffect => useEffectuseDeepMemo => useMemouseDeepCallback => useCallbackuseDeepImperativeHandle => useImperativeHandleuseDeepLayoutEffect => useLayoutEffectisEqual => سوف تحقق isequal بعمقcloneDeep => سوف يستنسخ كائن ومصفوفة بعمق قم دائمًا بتشغيل الشاشة المسبقة أثناء تطوير التطبيق لأنه سيخبرك Framerate و JS Framerate ، إذا كان أي إطار ينخفض ، فيمكنك التحقق من الرمز الجديد الذي يسببه لإسقاط الإطار وجعل وقتك إلى انخفاض التفاعل (TTI) ، فيمكنك فتح Dev Menu في التطبيق الخاص بك وتبديل Show Perf Monitor . 
لا تستخدم مطلقًا قائمة Flatlist ، استخدم دائمًا قائمة الفلاش لأنها تستخدم مفهوم طرق إعادة التدوير ، والتي تخلق فقط وتقديم عدد محدود من المشاهدات المرئية على الشاشة
قم بإنشاء مثيل مسجل مخصص وفرض الرموز التعبيرية لتصنيف السجلات. وبهذه الطريقة ، من الأسهل اكتشاف الخطوط ذات الصلة في وحدة التحكم الخاصة بك ، وتبدو أكثر ودية بشكل عام. قم بالكثير من التسجيل لإنقاذ نفسك من الليالي الطويلة من التصحيح في وقت لاحق! 
استخدم دائمًا المكجم الأصلي من REACTNavigation. نظرًا لأنه يستخدم بدايات الشاشة الأصلية للمنصة ، فإنه يستحق دائمًا مكاسب الأداء على المكدس المستند إلى JS. 
Redux إذا كنت تستخدم بالفعل Redux ، فيجب عليك استخدام وظائف "المحدد" المذكورة
React Context إذا كنت تستخدم بالفعل React Context ، فيجب عليك استخدام Countext-Selector لوظائف "Selector" المذكورة وإلا يتم تغيير قيمة السياق ، وجميع المكونات التي سيعيدها usecontext.
موصى به لاستخدام هذه libs الارتداد ، Jotai Zustand لإدارة الدولة
إذا كنت بحاجة إلى القيام بشيء ما في مكون الطفل من مكون الأصل ، فاستخدم Ref و UseimperativeHandle لاستدعاء وظائف مكونات الطفل من مكون الأصل بدلاً من اللعب مع تمرير مكون الطفل
استخدم شوكة React-Native-Puffer من CRAFTZDOG ، عند التعامل مع الكثير من المخازن المؤقتة لتسريع تطبيقك. يستخدم التطبيقات المدعومة C ++ المكشوفة من خلال JSI ، والتي هي أسرع 4x تقريبًا من تطبيق JS. 
استخدم MMKV من React-Native لتخزين البيانات واستردادها بشكل متزامن من التخزين المحلي ، والتي تستمر حتى في إطلاق التطبيق التالي. بالمقارنة مع LocalStorage على الويب ، يتيح لك MMKV أيضًا تشفير بياناتك والحصول على مثيلات متعددة! 
استخدم React-Native-Blurhash لإظهار أصحاب نائبة ضبابية جميلة لصورك ومقاطع الفيديو الخاصة بك. قم بإنشاء سلسلة قصيرة تمثل إصدارًا ضبابيًا من خادم المحتوى ("Blurhash") إلى جانب الخادم وأرسله إلى جانب بياناتك إلى التطبيق! 
عند تقديم الأرقام إلى المستخدم ، يجب عليك تنسيقها في اللغة الصحيح (فواصل ، علامات العملة ، ..) بينما. 
دائما التعامل مع المنطقة الآمنة insets بشكل مناسب. بدلاً من لف الشاشة بأكملها في أ ، يمكنك العمل مع الحشائش لإنشاء واجهة مستخدم أنظف.
هنا ، مررنا contentContainerStyle={{ paddingBottom: safeAreaBottom }} إلى:
اقرأ "فعالة حديثة C ++". حتى لو لم تكن مطورًا C ++ ، فسيساعدك هذا الكتاب على فهم كيفية عمل إدارة الذاكرة وتصدقه أو لا يؤثر ذلك على كيفية تفكيرك في React (الأصلي). في الواقع هذا هو كتاب البرمجة الوحيد الذي قرأته على الإطلاق
ستفهم لماذا {} === {} كاذب ، وكيف تعمل المساواة في الهوية ، وكيف تكون إعادة البيع أطنانًا من المخصصات ، وكيفية تجنب النسخ ، والكثير من الأشياء الأخرى حول الأداء التي تجعلك تفكر قليلاً عند كتابة التعليمات البرمجية. فقط لا تتحسن قبل الأوان؟
وإذا كنت ترغب في الذهاب إلى تطوير C ++ مع JSI ، فمن الأفضل أن تقرأ هذا الكتاب - C ++ ليس مسامحة مثل JS. إذا قمت بعمل مكتبة تحتوي على رمز C ++ السيئ فيها ، فسيكره المستخدمون لك لجعل تطبيقهم سيغابرت؟
لا تستخدم المكون أبدًا مباشرة. بدلاً من ذلك ، قم بإنشاء التجريد الخاص بك حتى لا تكرر نفسك باسم الخط أو حجم الخط أو الألوان في كل مرة ومن الأسهل تغيير الخصائص في أي وقت.
بالإضافة إلى ذلك ، قم بإنشاء قاعدة ESLINT لتحذيرك في كل مرة تحاول استخدامها بدلاً من 
عند التعامل مع الأرقام الكبيرة ، استخدم مومبًا للمواصفات المتأخرة بدلاً من أي من المكتبات المستندة إلى JS. ⚡ يتم دعمه بتنفيذ C ++ النقي وهو أسرع 330x من BN.JS في بعض التطبيقات (على سبيل المثال تطبيقات #Crypto ، Ethers.js ، الإهليلجي ، Bitcoin) 
عند العمل مع #Crypto / Cryptography ، استخدم React-native-crypto بدلاً من أي من المكتبات المستندة إلى JS. ⚡ يتم دعمه بتنفيذ C ++ النقي وهو ما يصل إلى 58x أسرع من رد فعل مفاعل أو تصفح التشفير في سيناريوهات معينة.
يمكنك استخدام مصباح يدوي لإنشاء درجة أداء لتطبيق Android الخاص بك
يمكنك القيام بالتوصيف لتحسين الأداء.
يجب عليك إزالة console.log من Prod App حيث أن استخدام عبارات console.log يقلل من FPS ، يمكنك إزالة console.log عن طريق قراءة هذا
بفضل مارك روسيفي ومارجيلو ، في الغالب أفضل الممارسات