javascript - React Native: en annen VirtualizedList-basert beholder
Etter å ha oppgradert til React Native 0.61, får jeg mange advarsler som dette:
VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.
Hva er den andre VirtualizedList-støttede beholderen som jeg bør bruke, og hvorfor anbefales det nå ikke å bruke den slik?
Svar #1
Hvis noen fortsatt leter etter et forslag til problemet som Ponleu og David Schilling har beskrevet her (angående innhold som går over FlatList), så er dette tilnærmingen jeg tok:
<SafeAreaView style={{flex: 1}}>
<FlatList
data={data}
ListHeaderComponent={ContentThatGoesAboveTheFlatList}
ListFooterComponent={ContentThatGoesBelowTheFlatList} />
</SafeAreaView>
Du kan lese mer om dette i ListHeaderComponent.
Svar #2
Bare i tilfelle dette hjelper noen, er dette hvordan jeg løste feilen i mitt tilfelle.
Jeg hadde en FlatList inne i en ScrollView:
render() {
return (
<ScrollView>
<Text>{'My Title'}</Text>
<FlatList
data={this.state.myData}
renderItem={({ item }) => {
return <p>{item.name}</p>;
}}
/>
{this.state.loading && <Text>{'Loading...'}</Text>}
</ScrollView>
);
}
og jeg kvittet meg med ScrollView ved å bruke FlatList for å gjengi alt jeg trengte, noe som kvittet seg med advarselen:
render() {
const getHeader = () => {
return <Text>{'My Title'}</Text>;
};
const getFooter = () => {
if (this.state.loading) {
return null;
}
return <Text>{'Loading...'}</Text>;
};
return (
<FlatList
data={this.state.myData}
renderItem={({ item }) => {
return <p>{item.name}</p>;
}}
ListHeaderComponent={getHeader}
ListFooterComponent={getFooter}
/>
);
}
Svar #3
Den beste måten er å deaktivere den advarselen, fordi noen ganger trenger Flatlist å være i ScrollView.
Oppdater React Native v0.63 eller nyere
YellowBox er nå endret og erstattet med LogBox.
Funksjonell
import React, { useEffect } from 'react';
import { LogBox } from 'react-native';
useEffect(() => {
LogBox.ignoreLogs(['VirtualizedLists should never be nested']);
}, [])
Klassbasert
import React from 'react';
import { LogBox } from 'react-native';
componentDidMount() {
LogBox.ignoreLogs(['VirtualizedLists should never be nested']);
}
Oppdater React Native v0.63 nedenfor
Funksjonell
import React, { useEffect } from 'react';
import { YellowBox } from 'react-native';
useEffect(() => {
YellowBox.ignoreWarnings(['VirtualizedLists should never be nested']);
}, [])
Klassebasert
import React from 'react';
import { YellowBox } from 'react-native';
componentDidMount() {
YellowBox.ignoreWarnings(['VirtualizedLists should never be nested']);
}
Svar #4
Data
// Dummy data array
const data = [
{id: 1, name: 'Tom'},
{id: 2, name: 'Jerry'},
]
Løsning #1
Du kan lage en egendefinert komponent for det slik:
const VirtualizedList = ({children}) => {
return (
<FlatList
data={[]}
keyExtractor={() => "key"}
renderItem={null}
ListHeaderComponent={
<>{children}</>
}
/>
)
}
Bruk deretter denne VirtualizedList som overordnet komponent:
...
return (
<VirtualizedList>
<FlatList
data={data}
keyExtractor={(item, index) => item.id + index.toString()}
renderItem={_renderItem}
/>
<AnyComponent/>
</VirtualizedList>
)
Løsning #2
Hvis du bruker FlatList inne i ScrollView, gir det en advarsel som er irriterende, så du kan bruke arrayens map-egenskap, slik:
Merk*: Det er ikke en anbefalt måte å vise en liste på. Hvis du har en liten mengde av det, kan du bruke det, det er helt greit, men hvis du vil vise en liste som får data fra en API og har mye data, kan du bruke andre løsninger. Hvis du bruker et kart med store mengder data, vil det påvirke ytelsen til appen din.
<ScrollView>
{data.map((item, index) => (
<View key={index}>
<Text>{item.name}</Text>
</View>
))}
</ScrollView>
Løsning #3
Hvis du gjør FlatList horisontal (i henhold til ditt behov), vil også advarselen forsvinne:
<ScrollView>
<FlatList
data={data}
keyExtractor={(item, index) => item.id + index.toString()}
horizontal={true}
/>
</ScrollView>
Løsning #4
Du kan legge til en topptekst- og bunntekstkomponent.
I ListHeaderComponent og ListFooterComponent kan du legge til hvilken som helst komponent, så du trenger ikke den overordnede ScrollView.
<FlatList
data={data}
keyExtractor={(item, index) => item.id + index.toString()}
ListHeaderComponent={headerComponent}
ListFooterComponent={footerComponent}
ListEmptyComponent={emptyComponent}
ItemSeparatorComponent={separator}
/>
// List components
const headerComponent = () => (
<View>
<Header/>
<Any/>
</View>
)
const footerComponent = () => (
<View>
<Footer/>
<Any/>
</View>
)
const emptyComponent = () => (
<View>
<EmptyView/>
<Any/>
</View>
)
const separator = () => (
<View style={{height: 0.8, width: '100%', backgroundColor: '#fff'}} />
)
Svar #5
Etter React Native 0.71, hvis du har prop scrollEnabled={false} i FlatList, skal ikke feilen vises lenger, som endringsloggen:
La til en sjekk for om scrollEnabled ikke er false, hvis det er tilfelle, utløser VirtualizedList-feilen
Svar #6
Advarselen vises fordi ScrollView og FlatList deler den samme logikken. Hvis FlatList kjører inne i ScrollView, blir det duplisert.
Forresten fungerer ikke SafeAreaView for meg. Den eneste måten å løse det på er:
<ScrollView>
{data.map((item, index) => {
...your code
}}
</ScrollView>
Feilen forsvinner.
Svar #7
Koden nedenfor fungerer perfekt for meg for å deaktivere den irriterende feilen:
VirtualizedLists bør aldri plasseres inni vanlige ScrollViews med samme retning, fordi det kan bryte vindusfunksjoner og annen funksjonalitet. Bruk i stedet en annen beholder som er basert på VirtualizedList.
React Native 0.68.2:
<ScrollView horizontal={false} style={{flex: 1}}>
<ScrollView
horizontal={true}
contentContainerStyle={{width: '100%', height: '100%'}}>
<FlatList ... />
</ScrollView>
</ScrollView>
