
React-Native-Best-Practice es una mejor práctica react-nativa y un paquete, que proporciona técnicas para aumentar el rendimiento y los servicios públicos para aumentar el rendimiento de la aplicación
Debe usar por qué se renderizas por qué te notifica sobre los re-renderizadores potencialmente evitables.
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/,
] ,
} ) ;
} Importar el código de archivo anterior en su aplicación Root index.js
Te permite omitir la re-retención de un componente cuando sus accesorios no cambian.
Es importante memorizar cálculos pesados, así como matrices y creaciones de objetos para que no se vuelvan a crear en cada renderizado. Un re-render se produce cuando el estado cambia, Redux despacha alguna acción o cuando el usuario escribe en una entrada de texto (volver a renderizar para cada llave presione). No querrá ejecutar muchas operaciones en esos renders por razones muy obvias, por lo que no hay filtrado pesado, sin operaciones de lista, etc.
Un componente puro (o un componente React.memo ) no vuelve a renderizar si sus accesorios son iguales .
Cada variable que cree en su función de renderizado se reasignará en cada renderizado. Si bien esto no es un problema para los tipos de valor , esto hace que los tipos de referencia sean diferentes en cada renderizado. Cuando pasa esas variables a componentes puros a través de accesorios, aún así volverán a renderizar a pesar de que los accesorios son lógicamente iguales. A menudo, esas variables incluso pasan por el puente y hacen que su aplicación sea lento.
Cuando un componente puro se vuelve a renderizar, compara los accesorios anteriores con los accesorios y verificaciones actuales si son de igualdad superficial .
Números , cadenas y booleanos son tipos de valor , lo que significa que se pueden comparar por valor :
const i1 = 7 ;
const i2 = 7 ;
const equal = i1 === i2 ; // trueLos objetos , matrices y funciones son tipos de referencia , lo que significa que no se pueden comparar por su valor lógico, pero deben compararse por referencia :
const o1 = { x : 7 } ;
const o2 = { x : 7 } ;
const equal = o1 === o2 ; // false Las comparaciones de referencia simplemente comparan la dirección de memoria de la variable, por lo que solo o1 === o1 sería true en el ejemplo de código anterior.
'ISEQUAL
fromREACT-NATIVO-BEST-PRACIPIC' para comparar objetos por igualdad real, pero eso ya no es una igualdad superficial .
Si crea objetos en su función de renderizado, se volverán a crear en cada renderizado. Esto significa que cuando crea un objeto en el primer render, no es igual a referencia al objeto en el segundo render. Por esta misma razón, la memoización existe.
useMemo para memorizar matrices y objetos que mantengan su igualdad de referencia (y no se recreará en cada renderizado) siempre que las dependencias (segundo argumento) permanezcan igual. También use useMemo para almacenar cálculos pesados, como operaciones de matriz, filtrado, etc.useCallback para memorizar una función.useDeepEffect , useDeepCallback , useDeepImperativeHandle y useDeepLayoutEffect de import {useDeepEffect, ...} from 'react-native-best-practice'En general, los componentes de la función se pueden optimizar más fácilmente debido al concepto de ganchos. Sin embargo, puede aplicar técnicas similares para los componentes de clase, solo tenga en cuenta que esto dará como resultado mucho más código.
Si bien las animaciones y las tareas intensivas de rendimiento están programadas en hilos nativos, toda su lógica comercial se ejecuta en un solo hilo de JavaScript, así que asegúrese de hacer el menor trabajo posible allí. Hacer demasiado trabajo en el hilo de JavaScript se puede comparar con un alto ping en un videojuego: aún puedes mirar a mi alrededor sin problemas, pero realmente no puedes jugar el juego porque cada interacción lleva demasiado tiempo.
Los componentes nativos ( <View> , <Text> , <Image> , <Blurhash> , ...) tienen que pasar accesorios a nativos a través del puente. Se pueden memorizar, por lo que React compara los accesorios para la igualdad superficial y solo los pasa sobre el puente si son diferentes a los accesorios del último render. Si no memoiza correctamente, puede pasar accesorios sobre el puente por cada renderizado, lo que hace que el puente esté muy ocupado. Vea el ejemplo de los estilos: ¡los estilos serán enviados por el puente en cada revénero!
Aquí hay algunos ejemplos para ayudarlo a evitar hacer demasiado trabajo en su hilo de JavaScript:
return < View style = { [ styles . container , { backgroundColor : 'red' } ] } /> ; const style = useMemo ( ( ) => [ styles . container , { backgroundColor : 'red' } ] , [ ] ) ;
return < View style = { style } /> ;useAnimatedStyle , ya que tienen que ser dinámicos. El uso filter , map u otras operaciones de matriz en renderistas ejecutará toda la operación nuevamente para cada renderizado.
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 > ; También puede aplicar esto para representar múltiples vistas de reacción con .map . Esos también se pueden memorizar con useMemo .
return < View onLayout = { ( layout ) => console . log ( layout ) } /> ; const onLayout = useCallback ( ( layout ) => {
console . log ( layout ) ;
} , [ ] ) ;
return < View onLayout = { onLayout } /> ; Asegúrese de pensar también en otras llamadas en el renderizador, por ejemplo, useSelector , useComponentDidAppear : ¡envuelva la devolución de llamada allí también!
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 } /> ;
} Esto se aplica a los objetos y a las funciones que no dependen del estado o los accesorios del componente. Siempre use esto si puede, ya que es aún más eficiente que useMemo y useCallback .
const [ me , setMe ] = useState ( users . find ( ( u ) => u . id === myUserId ) ) ; const [ me , setMe ] = useState ( ( ) => users . find ( ( u ) => u . id === myUserId ) ) ; El gancho useState acepta una función inicializador. Mientras que el primer ejemplo ("malo") ejecuta el .find en cada renderizado, el segundo ejemplo solo ejecuta la función pasada una vez para inicializar el estado.
Al escribir nuevos componentes, siempre pongo una declaración de registro en mi función de renderizado para ver pasivamente con qué frecuencia mis componentes se vuelven a renderizar mientras estoy trabajando en ello. En general, los componentes deberían volver a renderizar lo menos posible, y si veo que aparecen muchos registros en mi consola, sé que hice algo mal. Es una buena páctea poner esta función en su componente una vez que comience a trabajar en ella y eliminarla una vez hecho.
function ComponentImWorkingOn ( ) {
// code
console . log ( 're-rendering ComponentImWorkingOn!' ) ;
return < View /> ;
}También puede usar la biblioteca de por qué renderizar por qué se ha vuelto a hacer para averiguar por qué un componente ha vuelto a renderizar (cambios de accesorio, cambios de estado, ...) y posiblemente capturar errores desde el principio.
React.memo export const MyComponent = ( props ) => {
return ...
} const MyComponentImpl = ( props ) => {
return ...
}
export const MyComponent = React . memo ( MyComponentImpl ) ; Si su componente presenta el mismo resultado dado los mismos accesorios, puede envolverlo en una llamada para React.memo(...) Esto significa que React se saltará la representación del componente y reutilizará el último resultado renderizado. Vea los documentos oficiales para React.memo , y use React.memo(...) sabiamente.
Si su aplicación se siente lenta, pruebe la biblioteca React-Native-Rectorance y su complemento Flipper perfile el rendimiento de su aplicación en varios aspectos, como el tiempo de interactuar y el tiempo de componente , la ejecución del script y más.
No optimice prematuramente. Algunos ejemplos utilizados aquí (por ejemplo, el useMemo uno) son muy pequeños y solo demuestran la idea. Un gancho como `usememo también viene con un costo (asignando la función y la matriz DEPS, llamando al gancho real y ejecutando una comparación de matriz), así que tenga en cuenta que a menudo es mejor pasar por objetos o matrices directamente si el componente en sí está optimizado. Después de una cierta complejidad de los componentes o con un cierto gráfico de dependencia, las funciones de memoramiento pueden ser una gran victoria de rendimiento, pero también hay casos en los que solo conduce a un código innecesariamente complejo y, a veces, un rendimiento aún peor. ¡Siempre compare antes y después!
npm i react-native-best-practice
Todos los argumentos que pasan como en React Hooks nativos como
import {useDeepEffect} from 'react-native-best-practice'
useDeepEffect(()=>{
},[recreatedDeepObject])
useDeepEffect => useEffectuseDeepMemo => useMemouseDeepCallback => useCallbackuseDeepImperativeHandle => useImperativeHandleuseDeepLayoutEffect => useLayoutEffectisEqual => verificará a ISEqual profundamentecloneDeep => clonará objetos y matrizá profundamente Siempre active el monitor pref mientras desarrolla la aplicación, ya que le indicará la velocidad de marco de la interfaz de usuario y JS, si se cae el cuadro, puede verificar qué nuevo código está causando el marco de caída y hacer que su tiempo sea interactivo (TTI) bajo, puede abrir el Dev Menu en su aplicación y alternar Show Perf Monitor . 
Nunca use la lista plana, siempre use Flashlist, ya que utiliza el concepto de vistas de reciclaje, que solo crean y hacen un número limitado de vistas que son visibles en la pantalla
Cree una instancia de registrador personalizada y aplique emojis para clasificar los registros. De esta manera, es más fácil detectar líneas relevantes en su consola, y se ve más amigable en general. ¡Haga muchos registros para ahorrar de largas noches de depuración en un momento posterior! 
Siempre use la pila nativa de @reactnavigation. Dado que utiliza primitivas de pantalla nativas de plataforma, casi siempre vale la pena las ganancias de rendimiento sobre la pila basada en JS. 
Redux Si ya está usando Redux, entonces debe usar reseleccionar las funciones de "selector" memoizadas
React Context Si ya está utilizando el contexto React, entonces debe usar Use-Context-selector para funciones "selectores" memoizadas de otra manera, de lo contrario se cambia un valor de contexto, todos los componentes que ussexting volverá a renderizar.
Recomendado usar estos libs retroil, Jotai Zustand para la gestión estatal
Si necesita hacer algo en el componente infantil desde el componente principal, use REF y UseimperativeHandle para llamar a las funciones de los componentes infantiles desde el componente principal en lugar de jugar con el estado que pasa al componente infantil
Use la horquilla react-nativa-buffer de @CraftzDog, cuando se trata de muchos buffers para acelerar su aplicación. Utiliza implementaciones respaldadas por C ++ expuestas a través de JSI, que es aproximadamente 4 veces más rápido que la implementación basada en JS. 
Use React-Native-MMKV para almacenar y recuperar datos sincrónicamente del almacenamiento local, que persiste incluso en el próximo lanzamiento de la aplicación. ¡En comparación con LocalStorage en la web, MMKV también le permite cifrar sus datos y tener múltiples instancias! 
Use React-Native-Bhash para mostrar hermosos marcadores de posición borrosos para sus imágenes y videos. ¡Genere una cadena corta que represente una versión borrosa de su contenido ("Blurhash") del lado del servidor y envíela junto con sus datos a la aplicación! 
Al presentar números al usuario, debe formatearlos en la localidad correcta (comas, signos monetarios, ...) mientras que .tolocaleString (..) es un trabajo, ¡realmente puede construir su propia instancia de información numérica para mejorar el rendimiento en ~ 2x! 
Siempre maneje las inserciones de área segura adecuadamente. En lugar de envolver toda la pantalla en A, puede trabajar con los lanzamientos para crear UIS más limpias.
Aquí, pasamos contentContainerStyle={{ paddingBottom: safeAreaBottom }} a:
Lea "C ++ moderno efectivo". Incluso si no es un desarrollador de C ++, este libro lo ayudará a comprender cómo funciona la gestión de la memoria y lo cree o no afecta cómo piensa sobre React (nativo). De hecho, ese es el único libro de programación que leí
Entenderá por qué {} === {} es falso, cómo funciona la igualdad de identidad, cómo los re-renderizadores son toneladas de asignaciones, cómo evitar copias y muchas otras cosas sobre el rendimiento que solo te hace pensar un poco diferente cuando escribes código. ¿No optimiza prematuramente?
Y si quieres entrar en el desarrollo de C ++ con JSI, es aún mejor que leas este libro: C ++ no es tan indulgente como JS. Si hace una biblioteca que tiene un código C ++ malo, ¿los usuarios lo odiarán por hacer su aplicación Sigabrt?
Nunca use el componente directamente. En su lugar, cree su propia abstracción para que no se repita con el nombre de la fuente, el tamaño de la fuente o los colores cada vez y es más fácil cambiar las propiedades en cualquier momento.
Además, cree una regla de eslint para advertirle cada vez que intenta usar en lugar de ️ 
Cuando se trata de grandes números, use el número de bigüeño react-nativo en lugar de cualquiera de las bibliotecas basadas en JS. ⚡️ Está respaldado por una implementación pura de C ++ y es ~ 330x más rápido que bn.js en ciertas aplicaciones (por ejemplo, aplicaciones #crypto, ethers.js, elípticas, bitcoin) 
Cuando trabaje con #crypto / criptografía, use React-Native-Quick-Crypto en lugar de cualquiera de las bibliotecas basadas en JS. ⚡️ Está respaldado por una implementación pura de C ++ y es de hasta 58 veces más rápido que react-nativo-crypto o cripto-navegación en ciertos escenarios.
Puede usar la linterna para generar una puntuación de rendimiento para su aplicación Android
Puede hacer perfiles para la optimización del rendimiento.
Debe eliminar console.log de la aplicación Prod como usando console.log las declaraciones reduce el FPS, puede eliminar console.log leyendo esto
Gracias a Marc Rousavy y Margelo, ya que la mayoría de las mejores prácticas son sus