saleel / react-native-super-grid

Responsive Grid View for React Native

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"VirtualizedLists should never be nested..." in ScrollView

jackHedaya opened this issue · comments

Hi!

When nesting a FlatGrid component in a ScrollView, the following warning appears:

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

Adding a listKey did not work.

This looks like a general waning while nesting any List inside a ScrollView, and this would probably appear even while using native FlatList instead of FlatGrid.
Btw, what is the use case behind this approach? FlatGrid and FlatList area already scrollable. If you want content above or below the grid, maybe you can make use of ListHeaderComponent and ListFooterComponent.

I have a pretty complex view built where the grid is only used as one component, any way to silence the warning without having to rebuild the entire screen?

I think you're right, using ListHeaderComponent and ListFooterComponent is the move typically but in my case I'm not rendering that many items and am mostly using the Grid for positioning and styling. I just silenced the warnings in the component instead using the following:

useEffect(() => {
    LogBox.ignoreLogs(['VirtualizedLists should never be nested'])
}, [])

Following up to this, I think it'd be a great feature to have the option to use a non-list-based grid (and not just suppressing the console.error).

Looking into the source, it seems doable with the current code. If I have time, I'll give it a go; else, commenting here in the event that someone else needs it + wants to give it a shot!

@wkoutre I agree this would be nice to have the option to use a simple <View> instead of FlatList - in my case I want to have multiple grids on the same page (all scrollable inside a single ScrollView).

Since I only have ~10 items in each grid, virtualizing the grids isn't necessary and greatly complicates things for me.


In terms of how this library could support such an API - I think it would likely be cleanest if it was another component, but it could share a lot of the code with the existing FlatGrid (perhaps by factoring out a lot of the row rendering logic into a shared component).

@saleel is this something you'd be interested in supporting?

@idolize Yes, this is something we can add. I am a little busy at the moment, but can look in to this after a few weeks. But if anyone is interested in creating a PR I can check and merge it quickly.

I agree that making a new component would be the best approach in this case - one of the properties of FlatGrid is that all the extra props passed are forwarded to the underlying FlatList.
Some of the calculations are already outside the FlatList, and is shared between SectionList and FlatList. We should be able to reuse them.

@saleel Awesome - thanks!

I tried messing with this locally - using the same component for both and adding a useFlatList prop just for testing.

Here's what I came up with. It works - I basically just re-implemented a few of the FlatList concepts using normal Views (obviously this doesn't cover all FlatList features like header/footer components, etc.)

return useFlatList ? (
    <FlatList
      data={rows}
      extraData={totalDimension}
      renderItem={({ item, index, separators }) =>
        renderRow({
          rowItems: item,
          rowIndex: index,
          isLastRow: index === rows.length - 1,
          itemsPerRow,
          rowStyle,
          containerStyle,
          separators,
        })
      }
      style={[
        {
          ...(horizontal ? { paddingLeft: spacing } : { paddingTop: spacing }),
        },
        style,
      ]}
      onLayout={onLayoutLocal}
      keyExtractor={localKeyExtractor}
      {...restProps}
      horizontal={horizontal}
    />
  ) : (
    <View
      style={[
        {
          ...(horizontal ? { paddingLeft: spacing } : { paddingTop: spacing }),
        },
        style,
      ]}
    >
      {rows.map((row, index) => (
        <View key={localKeyExtractor(row, index)} onLayout={onLayoutLocal}>
          {renderRow({
            rowItems: row,
            rowIndex: index,
            isLastRow: index === rows.length - 1,
            itemsPerRow,
            rowStyle,
            containerStyle,
            separators: emptySeparators,
          })}
        </View>
      ))}
    </View>
  );

Feel free to use any of this, or let me know if you're too busy and would prefer someone contribute a PR.

@idolize This looks great. I will test this and make a new component in a few days/weeks. We can call it something like SimpleGrid.
I suppose we don't need to worry about adding all features of FlatList, at least for now.

Btw, if you have some time to spend on this, please go ahead with the PR.

This patch works.
You can use it according to the instructions in this issue Kureev/react-native-blur#444 (comment)

react-native-super-grid+4.2.0.patch

diff --git a/node_modules/react-native-super-grid/FlatGrid.js b/node_modules/react-native-super-grid/FlatGrid.js
index 1591e88..3959deb 100644
--- a/node_modules/react-native-super-grid/FlatGrid.js
+++ b/node_modules/react-native-super-grid/FlatGrid.js
@@ -25,6 +25,7 @@ const FlatGrid = memo(
       itemContainerStyle,
       keyExtractor,
       invertedRow,
+      useFlatList,
       ...restProps
     } = props;
 
@@ -157,25 +158,24 @@ const FlatGrid = memo(
     );
 
 
-    return (
+    return useFlatList ? (
       <FlatList
         data={rows}
-        ref={ref}
         extraData={totalDimension}
-        renderItem={({ item, index }) => renderRow({
-          rowItems: item,
-          rowIndex: index,
-          isLastRow: index === rows.length - 1,
-          itemsPerRow,
-          rowStyle,
-          containerStyle,
-        })
+        renderItem={({ item, index, separators }) =>
+          renderRow({
+            rowItems: item,
+            rowIndex: index,
+            isLastRow: index === rows.length - 1,
+            itemsPerRow,
+            rowStyle,
+            containerStyle,
+            separators,
+          })
         }
         style={[
           {
-            ...(horizontal
-              ? { paddingLeft: spacing }
-              : { paddingTop: spacing }),
+            ...(horizontal ? { paddingLeft: spacing } : { paddingTop: spacing }),
           },
           style,
         ]}
@@ -184,6 +184,29 @@ const FlatGrid = memo(
         {...restProps}
         horizontal={horizontal}
       />
+    ) : (
+      <View
+        style={[
+          {
+            ...(horizontal ? { paddingLeft: spacing } : { paddingTop: spacing }),
+          },
+          style,
+        ]}
+      >
+        {rows.map((row, index) => (
+          <View key={localKeyExtractor(row, index)} onLayout={onLayoutLocal}>
+            {renderRow({
+              rowItems: row,
+              rowIndex: index,
+              isLastRow: index === rows.length - 1,
+              itemsPerRow,
+              rowStyle,
+              containerStyle,
+              separators: null,
+            })}
+          </View>
+        ))}
+      </View>
     );
   }),
 );
@@ -207,6 +230,7 @@ FlatGrid.propTypes = {
   keyExtractor: PropTypes.func,
   listKey: PropTypes.string,
   invertedRow: PropTypes.bool,
+  useFlatList: PropTypes.bool,
 };
 
 FlatGrid.defaultProps = {
@@ -223,6 +247,7 @@ FlatGrid.defaultProps = {
   listKey: undefined,
   maxDimension: undefined,
   invertedRow: false,
+  useFlatList: false,
 };
 
 
diff --git a/node_modules/react-native-super-grid/index.d.ts b/node_modules/react-native-super-grid/index.d.ts
index 8957830..6b03f0d 100644
--- a/node_modules/react-native-super-grid/index.d.ts
+++ b/node_modules/react-native-super-grid/index.d.ts
@@ -79,6 +79,7 @@ export interface FlatGridProps<ItemType = any>
    * Items to be rendered. renderItem will be called with each item in this array.
    */
   data: ItemType[];
+  useFlatList?: boolean;
 }
 
 /**

@rushelex Good. In this pathc forgot add ref={ref} to the FlatList

I didn't get chance to create a new component SimpleGrid, and it looks like the patch works well for those interested. If anyone can create a PR for a new component (that dont use FlatList internally), I would be happy to review/merge.

I am closing this issue - as its been a while and also the original issue was addressed.