Szybkie listy w React Native bez obejść rozmiarów ani modułów natywnych
Jeśli kiedykolwiek budowałeś złożony interfejs w React Native, prawdopodobnie przeklinałeś listy. Standardowy FlatList zaczyna tracić klatki na sekundę na długich listach i przepełnia pamięć. FlashList od Shopify jest zauważalnie szybszy dzięki ponownemu użyciu komponentów, ale spróbuj nakarmić go elementami o nieprzewidywalnej wysokości, takimi jak posty z różną ilością tekstu i obrazów. Mikrozamrożenia podczas szybkiego przewijania lub drżenie układu zaczynają się, gdy lista próbuje odgadnąć rozmiary komórek przez estimatedItemSize.
Ostatnio zespół LegendApp wydał bibliotekę Legend List. Jest to komponent listowy napisany w całości w TypeScripcie, bez ani jednej linii kodu natywnego, który rozwiązuje dokładnie ten problem z dynamicznym rozmiarem.
Koncepcja
Głównym celem projektu jest zapewnienie zamiennika dla FlatList i FlashList z znajomym API, ale bez spadków wydajności na elementach o zmiennej wysokości. Deweloperzy celowo użyli tylko czystego JavaScriptu i TypeScripta. Nie trzeba linkować żadnych modułów natywnych. Uproszcza to budowanie dla Expo Go i wersji webowych, a także zmniejsza ryzyko zepsucia czegoś podczas aktualizacji wersji React Native.
Projekt jest lekki i działa jako zamiennik typu drop-in. Jeśli masz już ekran napisany z FlatList, podstawowa migracja wymaga tylko zmiany importu i nazwy komponentu.
Co potrafi biblioteka
Deweloperzy skupili się na typowych problemach z listami w aplikacjach mobilnych. Oto cztery rzeczy, które są tutaj zauważalnie wygodniejsze:
Dynamiczna wysokość out of the box. Nie musisz wcześniej obliczać dokładnych wymiarów kart ani przekazywać przybliżonych szacunków. Lista sama dostosowuje się do rozmiarów treści bez opóźnień renderowania.
Właściwy interfejs czatu. Klasyczna sztuczka do tworzenia ekranu wiadomości polega na odwróceniu listy przez
inverted. Powoduje to dziwne błędy z animacjami klawiatury, odwróconym przewijaniem i pozycjonowaniem. Legend List ma właściwośćalignItemsAtEnd, która wyrównuje treść do dolnej krawędzi bez odwracania, orazmaintainScrollAtEnd, która utrzymuje przewijanie na ostatniej wiadomości, gdy nadejdą nowe dane.Dwukierunkowe nieskończone przewijanie. Ładowanie danych w górę i w dół działa bez błysków białego ekranu i gwałtownych skoków pozycji widoku.
Kontrolowane recykling komórek. Poprzez właściwość
recycleItemsmożesz włączyć lub wyłączyć ponowne użycie komponentów. Jeśli złożony lokalnyuseStatejest przechowywany wewnątrz elementu listy, ponowne użycie czasami prowadzi do nieprzyjemnych efektów ubocznych z wyświetlaniem stanu kogoś innego. W Legend List recykling jest domyślnie wyłączony dla bezpieczeństwa, ale możesz go włączyć jedną linią dla maksymalnej szybkości.
Jak to wygląda w kodzie
Instalacja jest standardowa:
npm install @legendapp/list
# или через bun / yarn
bun add @legendapp/list
Importujemy komponent z podfolderu runtime i przekazujemy znajome właściwości:
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 },
})
Właściwość maintainVisibleContentPosition utrzymuje treść na ekranie, jeśli rozmiary elementów powyżej widocznego obszaru się zmienią lub nadejdą nowe dane.
Ograniczenia i plany
Repozytorium jest młode, pojawiło się pod koniec 2024 roku. W roadmapzie autorzy otwarcie stwierdzają, czego jeszcze nie ma:
- Siatki typu masonry (kafelki o różnych wysokościach)
- Przyklejone nagłówki
- Zakresy kolumn
- Oddzielne typy elementów (
getItemType)
Jeśli Twój ekran opiera się na złożonej siatce z przyklejonymi sekcjami, jest za wcześnie na migrację.
Kto powinien spróbować
Biblioteka jest przydatna dla tych, którzy mają dość walki ze skokami interfejsu na czatach, kanałach informacyjnych lub listach komentarzy. Jeśli FlashList podskakuje na Twoich dynamicznych kartach, a FlatList nie zapewnia płynności, której potrzebujesz, zainstaluj @legendapp/list w gałęzi testowej. zajmie to tylko kilka minut do sprawdzenia, ponieważ nie będziesz musiał zmieniać struktury komponentów ani pisać natywnych wrapperów.
Powiązane projekty