Listas Rápidas no React Native Sem Gambiarras de Tamanho ou Módulos Nativos
Se você já construiu uma interface complexa no React Native, provavelmente já xingou as listas. O FlatList padrão começa a perder FPS em listas longas e entope a memória. O FlashList da Shopify é notavelmente mais rápido graças à reutilização de componentes, mas tente alimentá-lo com elementos de altura imprevisível como posts com quantidades variadas de texto e imagens. Micro-travamentos durante rolagem rápida ou tremores de layout começam quando a lista tenta adivinhar tamanhos de células através de estimatedItemSize.
Recentemente, a equipe da LegendApp lançou a biblioteca Legend List. É um componente de lista escrito inteiramente em TypeScript, sem uma única linha de código nativo, que resolve exatamente essa dor de cabeça de dimensionamento dinâmico.
O Conceito
O principal objetivo do projeto é fornecer uma substituição para FlatList e FlashList com uma API familiar, mas sem quedas de desempenho em elementos de altura variável. Os desenvolvedores usaram deliberadamente apenas JavaScript e TypeScript puro. Nenhum módulo nativo precisa ser vinculado. Isso simplifica a construção para Expo Go e versões web, e também reduz o risco de quebrar algo ao atualizar a versão do React Native.
O projeto é leve e funciona como uma substituição direta. Se você já tem uma tela escrita com FlatList, uma migração básica só requer mudar o import e o nome do componente.
O Que a Biblioteca Pode Fazer
Os desenvolvedores focaram em problemas típicos com listas em aplicativos móveis. Aqui estão quatro coisas que são notavelmente mais convenientes aqui:
Altura dinâmica pronta para uso. Você não precisa pré-calcular dimensões exatas dos cards ou passar estimativas aproximadas. A lista se adapta aos tamanhos do conteúdo por conta própria sem atraso de renderização.
Interface de chat adequada. O truque clássico para criar uma tela de mensagens é inverter a lista através de
inverted. Isso causa bugs estranhos com animações de teclado, rolagem invertida e posicionamento. Legend List tem um propalignItemsAtEndque alinha o conteúdo na borda inferior sem inversão, emaintainScrollAtEndque mantém a rolagem na última mensagem quando novos dados chegam.Rolagem infinita bidirecional. O carregamento de dados para cima e para baixo funciona sem flashes de tela branca e saltos abruptos na posição da viewport.
Reciclagem controlada de células. Através do prop
recycleItems, você pode ativar ou desativar a reutilização de componentes. Se um estado local complexouseStatefor armazenado dentro de um elemento de lista, a reutilização às vezes leva a efeitos colaterais desagradáveis com a exibição do estado de outra pessoa. Na Legend List, a reciclagem é desativada por padrão para segurança, mas você pode ativá-la com uma única linha para velocidade máxima.
Como Isso Fica no Código
A instalação é padrão:
npm install @legendapp/list
# или через bun / yarn
bun add @legendapp/list
Importamos o componente da subpasta runtime e passamos 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 },
})
O prop maintainVisibleContentPosition mantém o conteúdo na tela se os tamanhos dos elementos acima da área visível mudarem ou novos dados chegarem.
Limitações e Planos
O repositório é jovem, apareceu no final de 2024. No roadmap, os autores declaram abertamente o que ainda não existe:
- Grids masonry (tiles de alturas variadas)
- Cabeçalhos fixos
- Spans de colunas
- Tipos de itens separados (
getItemType)
Se sua tela depende de um grid complexo com seções fixas, é cedo demais para migrar.
Quem Deveria Experimentar
A biblioteca é útil para quem está cansado de lutar contra saltos de interface em chats, feeds de notícias ou listas de comentários. Se o FlashList apresenta tremores em seus cards dinâmicos e o FlatList não oferece a suavidade necessária, instale @legendapp/list em um branch de teste. Leva alguns minutos para verificar já que você não precisará mudar a estrutura do componente ou escrever wrappers nativos.
Projetos relacionados