React-Native another VirtualizedList-backed contai

2020-05-25 04:05发布

问题:

After upgrading to react-native 0.61 i get a lot of warnings like that:

VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.

What is the other VirtualizedList-backed container that i should use, and why is it now advised not to use like that?

回答1:

If someone's still looking for a suggestion to the problem that @Ponleu and @David Schilling have described here (regarding content that goes above the FlatList), then this is the approach I took:

<SafeAreaView style={{flex: 1}}>
    <FlatList
      data={data}
      ListHeaderComponent={ContentThatGoesAboveTheFlatList}
      ListFooterComponent={ContentThatGoesBelowTheFlatList} />
</SafeAreaView>

You can read more about this here: https://facebook.github.io/react-native/docs/flatlist#listheadercomponent

Hopefully it helps someone. :)



回答2:

Just in case this helps someone, this is how I fixed the error in my case.

I had a FlatList nested inside a ScrollView:

render() {
    return (
        <ScrollView>
            <h1>{'My Title'}</h1>
            <FlatList
                data={this.state.myData}
                renderItem={({ item }) => {
                    return <p>{item.name}</p>;
                }}
            />
            {this.state.loading && <h2>{'Loading...'}</h2>}
        </ScrollView>
    );
}

and I got rid of the ScrollView by using the FlatList to render everything I needed, which got rid of the warning:

render() {
    const getHeader = () => {
        return <h1>{'My Title'}</h1>;
    };

    const getFooter = () => {
        if (this.state.loading) {
            return null;
        }
        return <h2>{'Loading...'}</h2>;
    };

    return (
        <FlatList
            data={this.state.myData}
            renderItem={({ item }) => {
                return <p>{item.name}</p>;
            }}
            ListHeaderComponent={getHeader}
            ListFooterComponent={getFooter}
        />
    );
}


回答3:

Looking at the examples in docs I've changed container from:

<ScrollView>
    <FlatList ... />
</ScrollView>

to:

<SafeAreaView style={{flex: 1}}>
    <FlatList ... />
</SafeAreaView>

and all those warnings disappeared.



回答4:

I tried some ways to solve this, including ListHeaderComponent or ListFooterComponent, but it all didn't fit for me.

layout I wanted to achieve is like this, and I wanted to get scrolled in once.

<ScrollView>
  <View>I'm the first view</View>
  <View>I'm the second view</View>
  <MyFlatList />
</ScrollView>

First I want to say thanks to this issue and comments, which gave me bunch of ideas.

I was thinking of ListHeaderComponent places above the Flatlist, but since my Flatlist's direction was column, the header I wanted to place went on the left of the Flatlist :(

Then I had to try on VirtualizedList-backed thing. I just tried to pack all components in VirtualizedList, where renderItems gives index and there I could pass components conditionally to renderItems.

I could have worked this with Flatlist, but I haven't tried yet.
Finally it looks like this.

<View>
  <Virtualizedlist
    data={[]}
    initialNumToRender={1}
    renderItem={(props)=>{
      props.index===0 ? (1st view here) : props.index===1 ? (2nd view here) : (my flatlist)
    }}
    keyExtractor={item => item.key}
    getItemCount={2}
    getItem={ (data, index) => {
      return {
        id: Math.random().toString(12).substring(0),
      }
    }}
  />
</View>

(inside which lazyly renders↓)
  <View>I'm the first view</View>
  <View>I'm the second view</View>
  <MyFlatList />  

and of course able to scroll the whole screen.



回答5:

In my opinion i can use map instead of FlatList. But in my case i wan't to show large list. Not using FlatList may cause performance issue. so i used this to suppress warning https://github.com/GeekyAnts/NativeBase/issues/2947#issuecomment-549210509



回答6:

The warning appears because ScrollView and FlatList share the same logic, if FlatList run inside ScrollView, it's duplicated

By the way SafeAreaView doesn't work for me, the only way to solve is

<ScrollView>
    {data.map((item, index) => {
        ...your code
    }}
</ScrollView>

The error disappears



回答7:

This problem come when you are using <FlatList /> inside <ScrollView> with the same orientation.

To fix this, just add "horizontal" to your FlatList :

<ScrollView>
    <FlatList **horizontal** ... />
</ScrollView>

NB : Your FlatList will rendered horizontally