Listas rápidas en React Native sin trucos de tamaño ni módulos nativos
Si alguna vez has construido una interfaz compleja en React Native, probablemente has maldecido las listas. El FlatList estándar comienza a perder FPS en listas largas y satura la memoria. FlashList de Shopify es notablemente más rápida gracias a la reutilización de componentes, pero intenta alimentarla con elementos de altura impredecible como publicaciones con diferentes cantidades de texto e imágenes. Los micro-congelamientos durante el desplazamiento rápido o el parpadeo del diseño comienzan cuando la lista intenta adivinar los tamaños de las celdas a través de estimatedItemSize.
Recently, the LegendApp team released the Legend List library. It's a list component written entirely in TypeScript, without a single line of native code, that solves exactly this dynamic sizing headache.
El Concepto
El objetivo principal del proyecto es proporcionar un reemplazo para FlatList y FlashList con una API familiar, pero sin caídas de rendimiento en elementos de altura variable. Los desarrolladores usaron deliberadamente solo JavaScript y TypeScript puro. No es necesario vincular módulos nativos. Esto simplifica la construcción para Expo Go y versiones web, y también reduce el riesgo de romper algo al actualizar la versión de React Native.
El proyecto es ligero y funciona como un reemplazo directo. Si ya tienes una pantalla escrita con FlatList, una migración básica solo requiere cambiar la importación y el nombre del componente.
Lo que puede hacer la biblioteca
Los desarrolladores se centraron en problemas típicos con listas en aplicaciones móviles. Aquí hay cuatro cosas que son notablemente más convenientes aquí:
Altura dinámica lista para usar. No necesitas calcular previamente las dimensiones exactas de las tarjetas ni pasar estimaciones aproximadas. La lista se adapta a los tamaños del contenido por sí sola sin retraso de renderizado.
Interfaz de chat adecuada. El truco clásico para crear una pantalla de mensajería es voltear la lista a través de
inverted. Esto causa errores extraños con las animaciones del teclado, el desplazamiento invertido y el posicionamiento. Legend List tiene una propalignItemsAtEndque alinea el contenido al borde inferior sin inversión, ymaintainScrollAtEndque mantiene el desplazamiento en el último mensaje cuando llegan nuevos datos.Desplazamiento infinito bidireccional. Cargar datos hacia arriba y hacia abajo funciona sin destellos de pantalla blanca y saltos abruptos en la posición del viewport.
Reciclado de celdas controlado. A través de la prop
recycleItems, puedes habilitar o deshabilitar la reutilización de componentes. Si unuseStatelocal complejo se almacena dentro de un elemento de lista, la reutilización a veces genera efectos secundarios no deseados al mostrar el estado de otra persona. En Legend List, el reciclaje está deshabilitado por defecto por seguridad, pero puedes habilitarlo con una sola línea para máxima velocidad.
Cómo se ve en el código
La instalación es estándar:
npm install @legendapp/list
# или через bun / yarn
bun add @legendapp/list
Importamos el componente desde la subcarpeta runtime y pasamos props familiares:
import React, { useRef } from "react"
import { View, Image, Text, StyleSheet } from "react-native"
import { LegendList, LegendListRef, LegendListRenderItemProps } from "@legendapp/list/react-native"
interface PostItem {
id: string
author: string
content: string
photoUrl?: string
}
export const FeedScreen = ({ posts }: { posts: PostItem[] }) => {
const listRef = useRef<LegendListRef | null>(null)
const renderItem = ({ item }: LegendListRenderItemProps<PostItem>) => {
return (
<View style={styles.card}>
<Text style={styles.author}>{item.author}</Text>
<Text style={styles.text}>{item.content}</Text>
{item.photoUrl && (
<Image source={{ uri: item.photoUrl }} style={styles.image} />
)}
</View>
)
}
return (
<LegendList
data={posts}
renderItem={renderItem}
keyExtractor={(item) => item.id}
recycleItems={true}
maintainVisibleContentPosition
ref={listRef}
/>
)
}
const styles = StyleSheet.create({
card: { padding: 16, borderBottomWidth: 1, borderColor: "#eee" },
author: { fontWeight: "bold", marginBottom: 4 },
text: { fontSize: 14, lineHeight: 20 },
image: { width: "100%", height: 200, marginTop: 8, borderRadius: 8 },
})
La prop maintainVisibleContentPosition mantiene el contenido en pantalla si los tamaños de los elementos por encima del área visible cambian o llegan nuevos datos.
Limitaciones y planes
El repositorio es reciente, apareció a finales de 2024. En la hoja de ruta, los autores declaran abiertamente lo que aún no está:
- Cuadrículas masonry (mosaicos de diferentes alturas)
- Encabezados pegajosos
- Span de columnas
- Tipos de elementos separados (
getItemType)
Si tu pantalla depende de una cuadrícula compleja con secciones pegajosas, es demasiado pronto para migrar.
Quién debería probarlo
La biblioteca es útil para quienes están cansados de luchar contra los saltos de interfaz en chats, feeds de noticias o listas de comentarios. Si FlashList tiene temblores en tus tarjetas dinámicas y FlatList no te da la suavidad que necesitas, instala @legendapp/list en una rama de prueba. Solo toma un par de minutos verificar ya que no necesitarás cambiar la estructura del componente ni escribir envoltorios nativos.
Proyectos relacionados