
React-Con-Best-Gractice -это наилучшая практика реагирования и пакет, который предоставляет методы повышения производительности, а также утилиты для повышения производительности приложения
Вам следует использовать, почему-то, что уведомил вас о потенциально избегаемых повторных рендерингах.
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/,
] ,
} ) ;
} Импорт выше файлового кода в приложение root index.js
Позволяет вам пропустить повторное рендеринг компонента, когда его реквизит не изменяются.
Важно запомнить тяжелые вычисления, а также массивы и создания объектов, чтобы они не были воссозданы на каждом рендере. Повторная рендеринг происходит при изменении состояния, Redux отправляет какое-то действие или когда пользователь вводит в текстовый ввод (повторный Render для каждого нажатия клавиш). Вы не хотите выполнять много операций в этих рендерах по очень очевидным причинам - так что нет тяжелой фильтрации, без операций списков и т. Д.
Чистый компонент (или 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 в приведенном выше примере кода.
«Иквальны
fromреагируемой и наиболее высокой практики», чтобы сравнить объекты по фактическому равенству, но это больше не мелкое равенство .
Если вы создаете объекты в своей функции рендеринга, они будут воссозданы на каждом отдельном рендере. Это означает, что когда вы создаете объект на первом рендере, он не является ссылкой на объект во втором рендере. По этой причине существует памятка.
useMemo , чтобы запомнить массивы и объекты, которые будут сохранять их справочное равенство (и не будет воссоздаваться на каждом рендере), пока зависимости (второй аргумент) остаются прежними. Также используйте useMemo для кэширования тяжелых вычислений, таких как операции массива, фильтрация и т. Д.useCallback , чтобы запомнить функцию.useDeepEffect , useDeepCallback , useDeepImperativeHandle и useDeepLayoutEffect из import {useDeepEffect, ...} from 'react-native-best-practice'В целом, функциональные компоненты могут быть оптимизированы легче благодаря концепции крючков. Однако вы можете применить аналогичные методы для компонентов класса, просто имейте в виду, что это приведет к гораздо большему коду.
В то время как анимации и интенсивные задачи на собственные потоки запланированы, вся ваша бизнес -логика работает на одной ветке JavaScript, поэтому убедитесь, что вы выполняете как можно меньше работы. Слишком много работы над веткой JavaScript можно сравнить с высоким пингом в видеоигры - вы все равно можете осмотреть вокруг, но вы не можете играть в игру, потому что каждое взаимодействие занимает слишком много времени.
Нативные компоненты ( <View> , <Text> , <Image> , <Blurhash> , ...) должны передавать реквизиты на родной через мост. Их можно запомнить, поэтому реагирует сравнение реквизитов для мелкого равенства и передает их только по мосту, только если они отличаются от реквизита от последнего визуализации. Если вы не запоминаете правильно, вы можете пропустить реквизиты через мост за каждый отдельный рендеринг, заставляя мост был очень занятым. Смотрите пример стилей - стили будут отправлены через мост на каждом повторном рендеринге!
Вот несколько примеров, которые помогут вам избежать слишком большой работы над вашей веткой 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 } /> ; Обязательно подумайте о других вызовах в рендерере, например, 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 Hook принимает функцию инициализатора. В то время как первый пример («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-Contive-Performance, а также плагин Flipper, чтобы профилировать производительность вашего приложения в различных аспектах, таких как время до интерактивного , время рендеринга компонента , выполнение скрипта и многое другое.
Не оптимизируйте. Некоторые примеры, используемые здесь (например, 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 => будет клонировать объект и глубоко Всегда включайте монитор PREF во время разработки приложения, так как оно сообщает вам кадр пользовательского интерфейса и кадр JS, если какой -либо кадр падает, то вы можете проверить, какой новый код вызывает для сброса кадра и уделяет ваше время для интерактивного (TTI) низкого уровня, вы можете открыть Dev Menu в своем приложении и Togge Show Perf Monitor . 
Никогда не используйте Flatlist, всегда используйте Flashlist, поскольку он использует концепцию видов утилизации, которая только создает и производит ограниченное количество просмотров, которые видны на экране
Создайте пользовательский экземпляр журнала и применить смайлики для классификации журналов. Таким образом, в вашей консоли легче определить соответствующие линии и в целом выглядит более дружелюбным. Сделайте много журнала, чтобы спасти себя от долгих ночей отладки в более позднем этапе! 
Всегда используйте Native Stack от @reactnavigation. Поскольку он использует примитивы на экране платформы, он почти всегда стоит того, чтобы производительность на основе JS на основе JS. 
Redux, если вы уже используете Redux, то вы должны использовать повторный выбор для функций «Селектор» Memosed
React Context Если вы уже используете контекст React, вам следует использовать функции использования контекста для памятных «селектор», иначе значение контекста изменяется, все компоненты, которые useContext повторно видит.
Рекомендуется использовать эти Libs Recoil, Jotai Zustand для государственного управления
Если вам нужно что -то сделать в детском компоненте из родительского компонента, используйте ref и usereMperativehandle для вызова функций компонентов дочерних компонентов из родительских компонентов вместо игры с государством, передаваемым в детские компоненты
Используйте вилку React-C-Buffer от @Craftzdog, когда имеете дело с множеством буферов, чтобы ускорить ваше приложение. Он использует реализации C ++, подвергшихся поддержке JSI, что примерно в 4 раза быстрее, чем реализация на основе JS. 
Используйте React-MMKV для синхронного хранения и извлечения данных из локального хранилища, что сохраняется даже при следующем запуска приложения. По сравнению с LocalStorage в Интернете MMKV также позволяет зашифровать ваши данные и иметь несколько экземпляров! 
Используйте React-Clurhash, чтобы показать красивые размытые заполнители для ваших изображений и видео. Создайте короткую строку, которая представляет собой размытую версию вашего контента ("Blurhash") на стороне сервера и отправьте ее вместе с вашими данными в приложение! 
При представлении чисел пользователю вы должны отформатировать их в правильной локале (запятые, валютные знаки, ..) В то время как .tolocalestring (..) Делает ли это задание, вы можете построить свой собственный экземпляр NumberFormat, чтобы повысить производительность ~ 2x! 
Всегда обрабатывайте безопасные вставки зоны соответствующим образом. Вместо того, чтобы обернуть весь экран в a, вы можете работать с прокладками, чтобы создать более чистые интерфейсы.
Здесь мы прошли contentContainerStyle={{ paddingBottom: safeAreaBottom }} к:
Читайте «Эффективный современный C ++». Даже если вы не разработчик C ++, эта книга поможет вам понять, как работает управление памятью, и верите, или нет, это влияет на то, как вы думаете о React (Native). На самом деле это единственная книга программирования, которую я когда -либо читал
Вы поймете, почему {} === {} является ложным, как работает равенство идентификации, как повторные рестораны-это тонны распределений, как избежать копий и множество других вещей о производительности, которые просто заставляют вас думать немного по-другому при написании кода. Просто не оптимизируйте?
И если вы хотите перейти в разработку C ++ с JSI, то еще лучше, чтобы вы прочитали эту книгу - C ++ не так прощают, как JS. Если вы создаете библиотеку, в которой есть плохой код C ++, пользователи будут ненавидеть вас за то, что вы делаете свое приложение Sigabrt?
Никогда не используйте компонент напрямую. Вместо этого создайте свою собственную абстракцию, чтобы вы не повторяли себя с именем шрифта, размером шрифта или цветами каждый раз, и в любой момент легче менять свойства.
Кроме того, создайте правило Eslint, чтобы предупредить вас каждый раз, когда вы пытаетесь использовать вместо ️ 
При работе с большими числами используйте реагирующие битьюн вместо любой из библиотек на основе JS. ⚡ Он подкреплен чистой реализацией C ++ и на ~ 330x быстрее, чем BN.JS в определенных приложениях (например, приложения #Crypto, Ethers.js, Elliptic, Bitcoin) 
При работе с #Crypto / Cryptography используйте React-intive-quick-crypto вместо любой из библиотек на основе JS. ⚡ Он подкреплен чистой реализацией C ++ и находится в 58 раза быстрее, чем реагируют-корипту или крипто-браузериф в определенных сценариях.
Вы можете использовать фонарик для получения результатов производительности для вашего приложения Android
Вы можете сделать профилирование для оптимизации производительности.
Вы должны удалить console.log из приложения Prod в качестве использования console.log console.log.
Благодаря Марку Русави и Маргело, поскольку лучшие практики являются их