Schnelle Listen in React Native ohne Größen-Workarounds oder Native Module
Wenn Sie jemals eine komplexe Oberfläche in React Native erstellt haben, haben Sie wahrscheinlich über Listen geflucht. Die Standard-FlatList beginnt bei langen Listen FPS zu verlieren und verstopft den Speicher. FlashList von Shopify ist dank Komponentenwiederverwendung spürbar schneller, aber versuchen Sie, ihr Elemente mit unvorhersehbarer Höhe zu füttern, wie Beiträge mit unterschiedlichen Text- und Bildmengen. Mikro-Freezes beim schnellen Scrollen oder Layout-Jitter treten auf, wenn die Liste versucht, Zellgrößen durch estimatedItemSize zu schätzen.
Kürzlich hat das LegendApp-Team die Legend List-Bibliothek veröffentlicht. Es ist eine Listenkomponente, die vollständig in TypeScript geschrieben wurde, ohne eine einzige Zeile nativen Code, die genau dieses dynamische Größenproblem löst.
Das Konzept
Das Hauptziel des Projekts ist es, einen Ersatz für FlatList und FlashList mit einer vertrauten API bereitzustellen, aber ohne Leistungseinbußen bei Elementen mit variabler Höhe. Die Entwickler haben bewusst nur reines JavaScript und TypeScript verwendet. Es müssen keine nativen Module verknüpft werden. Dies vereinfacht den Build für Expo Go und Web-Versionen und reduziert auch das Risiko, beim Aktualisieren der React-Native-Version etwas zu beschädigen.
Das Projekt ist leichtgewichtig und funktioniert als Drop-in-Ersatz. Wenn Sie bereits einen Screen mit FlatList geschrieben haben, erfordert eine grundlegende Migration nur das Ändern des Imports und des Komponentennamens.
Was die Bibliothek kann
Die Entwickler konzentrierten sich auf typische Probleme mit Listen in mobilen Apps. Hier sind vier Dinge, die hier spürbar bequemer sind:
Dynamische Höhe out of the box. Sie müssen keine exakten Kartenabmessungen vorberechnen oder ungefähre Schätzungen übergeben. Die Liste passt sich von selbst an Inhaltsgrößen an, ohne Render-Lag.
Ordentliche Chat-Oberfläche. Der klassische Trick zum Erstellen eines Messaging-Screens ist, die Liste durch
invertedzu flippen. Dies verursacht seltsame Bugs bei Keyboard-Animationen, invertiertem Scrollen und Positionierung. Legend List hat einalignItemsAtEnd-Prop, das Inhalte ohne Invertierung am unteren Rand ausrichtet, undmaintainScrollAtEnd, das den Scroll beim letzten Nachricht hält, wenn neue Daten eintreffen.Bidirektionales unendliches Scrollen. Das Laden von Daten nach oben und unten funktioniert ohne weiße Bildschirmblitze und abrupte Sprünge in der Viewport-Position.
Kontrollierte Zellrecycling. Durch das
recycleItems-Prop können Sie die Komponentenwiederverwendung aktivieren oder deaktivieren. Wenn ein komplexer lokaleruseStatein einem Listenelement gespeichert ist, führt die Wiederverwendung manchmal zu unangenehmen Nebeneffekten beim Anzeigen des Zustands eines anderen. In Legend List ist das Recycling standardmäßig aus Sicherheitsgründen deaktiviert, aber Sie können es mit einer einzigen Zeile für maximale Geschwindigkeit aktivieren.
Wie es im Code aussieht
Die Installation ist Standard:
npm install @legendapp/list
# или через bun / yarn
bun add @legendapp/list
Wir importieren die Komponente aus dem Runtime-Unterordner und übergeben vertraute Props:
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 },
})
Das maintainVisibleContentPosition-Prop hält Inhalte auf dem Bildschirm, wenn sich die Größen von Elementen über dem sichtbaren Bereich ändern oder neue Daten eintreffen.
Einschränkungen und Pläne
Das Repository ist jung, es erschien Ende 2024. In der Roadmap geben die Autoren offen an, was noch nicht vorhanden ist:
- Masonry-Grids (Kacheln unterschiedlicher Höhe)
- Sticky Headers
- Column Spans
- Separate Elementtypen (
getItemType)
Wenn Ihr Screen auf einem komplexen Grid mit sticky Abschnitten basiert, ist es zu früh für eine Migration.
Für wen es sich lohnt, es zu versuchen
Die Bibliothek ist nützlich für diejenigen, die es leid sind, gegen Interfacesprünge in Chats, Newsfeeds oder Kommentarlisten zu kämpfen. Wenn FlashList bei Ihren dynamischen Karten ruckelt und FlatList nicht die gewünschte Glätte bietet, installieren Sie @legendapp/list in einem Test-Branch. Es dauert ein paar Minuten zum Überprüfen, da Sie die Komponentenstruktur nicht ändern oder native Wrapper schreiben müssen.
Ähnliche Projekte