Blog
Generisches ListItem in React Native mit TypeScript

Bei der Verwendung von React Native werden Listen mit der FlatList-Komponente erstellt. Eine FlatList wird aus einem oder mehreren wiederholbaren Listenelementen erstellt, ein Element pro Zeile. In diesem Blog zeige ich Ihnen, wie TypeScript bei der Erstellung von FlatLists mit generischen Listenelementen helfen kann.
Dies ist eine Technik, mit der wir Boilerplate reduzieren können, aber dennoch lesbare und anpassbare FlatLists haben.
Lassen Sie uns gleich in die Grundlagen einer FlatList eintauchen, indem wir eine Liste mit StarWars-Charakteren erstellen.
const starWarsData: StarWars[] = [
{id: '1', character: 'Luke Skywalker', hairColor: 'Blond'},
{id: '2', character: 'Leia Organa', hairColor: 'Brown'}
];
const StarWarsListItem = ({item}: {item: StarWars}) => (
<TouchableOpacity style={styles.item} onPress={() => onPressListItem(item)}>
<View style={styles.textContainer}>
<Text>Character: {item.character}</Text>
<Text>Hair color: {item.hairColor}</Text>
</View>
</TouchableOpacity>
);
return (
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text style={styles.headerLabel}>Star Wars Characters</Text>
</View>
<FlatList
data={starWarsData}
keyExtractor={(item) => item.id}
renderItem={StarWarsListItem}
/>
</View>
);Dieser Code generiert eine Liste von Charakteren aus StarWars, wie hier gezeigt.

GenericList
Wenn wir mehrere gleich aussehende FlatLists erstellen, wollen wir nicht jedes Mal den gleichen Code schreiben. Im obigen Beispiel sehen wir, dass die lila Überschrift in jeder FlatList erstellen.
type Props<ItemT> = {
data?: ItemT[];
onPressListItem: (item: ItemT) => void;
renderDetails: React.FC<{item: ItemT}>;
keyExtractor: (item: ItemT) => string;
headerTitle: string;
};
const GenericList = <ItemT,>({
data,
onPressListItem,
keyExtractor,
headerTitle,
renderDetails: RenderDetailsComponent
}: Props<ItemT>) => {
const renderItem = ({item}: {item: ItemT}) => (
<TouchableOpacity style={styles.item} onPress={() => onPressListItem(item)}>
<View style={styles.textContainer}>
<RenderDetailsComponent item={item} />
</View>
</TouchableOpacity>
);
return (
<FlatList
data={data}
keyExtractor={keyExtractor}
renderItem={renderItem}
ListHeaderComponent={
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text style={styles.headerLabel}>{headerTitle}</Text>
</View>
</View>
}
ItemSeparatorComponent={() => <View style={styles.listSeparator} />}
/>
);
};Die Komponente GenericList erhält Requisiten, die im Typ Props deklariert sind. Wenn wir uns den Typ renderDetails ansehen, sehen wir die folgende Deklaration: React.FC<{item: ItemT}>.
Diese Deklaration teilt TypeScript mit, dass es nur funktionale Komponenten akzeptieren soll, die die Prop item mit dem generischen Typ ItemT haben. Dieser generische Typ
Außerdem wird die <ItemT,> Kommasyntax benötigt, weil wir eine funktionale Komponente mit einer Pfeilfunktion verwenden. Andernfalls zeigt TypeScript den folgenden Fehler an:
Parsing error: JSX element ‘ItemT’ has no corresponding closing tag
Verschiedene Datensätze verwenden
Der folgende Code zeigt, wie Sie die StarWars FlatList erstellen, indem Sie die gerade gezeigte Komponente GenericList verwenden.
const starWarsData: StarWars[] = [
{id: '1', character: 'Luke Skywalker', hairColor: 'Blond'},
{id: '2', character: 'Leia Organa', hairColor: 'Brown'}
];
const StarWarsListItem = ({item}: {item: StarWars}) => (
<>
<Text>Character: {item.character}</Text>
<Text>Hair color: {item.hairColor}</Text>
</>
);
<GenericList
data={starWarsData}
headerTitle="StarWars characters"
renderDetails={StarWarsListItem}
onPressListItem={(item: StarWars) => console.log(item)}
keyExtractor={(item) => item.id}
/>Der Vorteil dieser Technik ist die hohe Flexibilität bei der Darstellung von Zeilen in einer FlatList, während der replizierte Code durch die Komponente GenericList verborgen wird. Letztendlich wird dies die Testbarkeit, die Wartung und die Erfahrung der Entwickler verbessern.
Wir können die GenericList auch mit anderen Daten verwenden, wie im folgenden Codebeispiel gezeigt.
const onPressListItem = (item: Fruit | StarWars) => console.log(item);
const StarWarsListItem = ({item}: {item: StarWars}) => (
<>
<Text>Character: {item.character}</Text>
<Text>Hair color: {item.hairColor}</Text>
</>
);
const FruitListItem = ({item}: {item: Fruit}) => <Text>{item.title}</Text>;
return (
<>
<GenericList
data={starWarsData}
headerTitle="StarWars characters"
renderDetails={StarWarsListItem}
onPressListItem={(item: StarWars) => console.log(item)}
keyExtractor={(item) => item.id}
/>
<GenericList
data={fruitData}
headerTitle="Fruits"
renderDetails={FruitListItem}
onPressListItem={onPressListItem}
keyExtractor={(item) => item.id}
/>
</>
);Auf diese Weise werden zwei Listen erstellt, die einen unterschiedlichen Datentyp verwenden und dennoch flexibel sind, was die Darstellung der Daten in den einzelnen Zeilen betrifft
Die folgende (eingebettete) CodeSandbox zeigt die Komponente GenericList mit react-native-web. Wenn Sie auf ein ListItem klicken, erhalten Sie ein Protokoll in der Konsole.
Danke, dass Sie meinen Blog lesen!
Verfasst von

Bart den Hollander
Unsere Ideen
Weitere Blogs
Contact



