Una app React Native que va fluida en el emulador y a tirones en un móvil de gama media es casi un rito de paso. Lo he vivido varias veces, y casi siempre el culpable no era React Native, sino cómo lo estábamos usando. Aquí van siete errores de rendimiento concretos, con el arreglo que aplico en cada caso.
1. Renderizar listas largas con .map() en un ScrollView
El clásico. Un ScrollView monta todos sus hijos de golpe; con 500 elementos, la app se congela al abrir la pantalla.
// ❌ Mal: monta los 500 a la vez
<ScrollView>
{items.map((item) => <Row key={item.id} item={item} />)}
</ScrollView>
// ✅ Bien: FlatList solo renderiza lo visible
<FlatList
data={items}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <Row item={item} />}
/>
FlatList virtualiza: monta y desmonta filas según el scroll. La diferencia en listas grandes es abismal.
2. Olvidar keyExtractor (o usar el índice como key)
Usar el índice del array como key provoca re-renders innecesarios y bugs visuales al reordenar. Usa siempre un identificador estable y único, como el id del elemento.
3. Funciones y objetos nuevos en cada render
Cada vez que pasas una función inline como prop, creas una referencia nueva, y el hijo se vuelve a renderizar aunque nada haya cambiado.
// ❌ Nueva función en cada render
<Row onPress={() => selectItem(item.id)} />
// ✅ Memoiza con useCallback
const handlePress = useCallback((id) => selectItem(id), [selectItem])
<Row onPress={handlePress} />
Combínalo con React.memo en el componente hijo para que solo se repinte cuando sus props cambian de verdad.
4. Imágenes sin dimensionar
Cargar una imagen de 3000 px para mostrarla a 100 px desperdicia memoria y CPU. Redimensiona en el servidor o usa una librería con caché como react-native-fast-image, y define siempre width y height explícitos para evitar reflows.
<FastImage
style={{ width: 100, height: 100 }}
source={{ uri: item.thumbnail, priority: FastImage.priority.normal }}
resizeMode={FastImage.resizeMode.cover}
/>
5. Animaciones en el hilo de JavaScript
Si animas con setState, cada frame pasa por el puente JS y notas los tirones. Usa la API Animated con useNativeDriver: true para que la animación corra en el hilo nativo.
Animated.timing(opacity, {
toValue: 1,
duration: 300,
useNativeDriver: true, // 👈 la clave
}).start()
6. Cálculos pesados en el render
Filtrar u ordenar un array grande dentro del cuerpo del componente se ejecuta en cada render. Envuélvelo en useMemo para que solo se recalcule cuando cambian sus dependencias.
const sorted = useMemo(
() => [...items].sort((a, b) => b.date - a.date),
[items]
)
7. No medir antes de optimizar
El error que engloba a todos los demás: optimizar a ciegas. Antes de tocar nada, perfila. Usa el Flipper o el profiler de React DevTools para ver qué componentes se renderizan de más y dónde se va el tiempo. Optimizar sin medir es adivinar.
Conclusión
El rendimiento en React Native rara vez se arregla con un truco mágico; es la suma de decisiones pequeñas: virtualizar listas, memoizar lo que toca, tratar bien las imágenes y animar en el hilo nativo. Nosotros aplicamos esta misma checklist en cada app que entregamos en Galadrim, porque una app fluida no es un lujo: es lo que separa un producto que la gente usa de uno que desinstala.
Si quieres profundizar en desarrollo móvil con React Native, en el equipo de Galadrim publicamos y trabajamos con estas tecnologías a diario.
Escrito por el equipo de Galadrim, agencia de desarrollo web, móvil e IA especializada en React, React Native y Node.js.
Top comments (0)