Repository: kiwicom/mobile
Pull request #1365 (2018-11-29 14:56:30)

Hotels: Replace scroll view with flatlist in search result list


Patch:
diff --git a/app/hotels/src/allHotels/AllHotelsSearchList.js b/app/hotels/src/allHotels/AllHotelsSearchList.js
index 96be6bd1..6a4e1882 100644
--- a/app/hotels/src/allHotels/AllHotelsSearchList.js
+++ b/app/hotels/src/allHotels/AllHotelsSearchList.js
@@ -1,6 +1,7 @@
 // @flow strict
 
 import * as React from 'react';
+import { FlatList } from 'react-native';
 import { GeneralError } from '@kiwicom/mobile-shared';
 import { createFragmentContainer, graphql } from '@kiwicom/mobile-relay';
 import { Translation } from '@kiwicom/mobile-localization';
@@ -11,7 +12,12 @@ import { withHotelsContext, type HotelsContextState } from '../HotelsContext';
 
 type Props = {|
   +data: AllHotelsSearchListProps | Array<?empty>,
-  setHotelId: (id: string) => void,
+  +setHotelId: (id: string) => void,
+  +ListFooterComponent: React.Node,
+|};
+
+type HotelType = {|
+  +id: string,
 |};
 
 export class AllHotelsSearchList extends React.Component<Props> {
@@ -23,6 +29,16 @@ export class AllHotelsSearchList extends React.Component<Props> {
     }
   }
 
+  keyExtractor = (item: ?HotelType) => item?.id;
+
+  renderItem = ({ item, index }: {| +item: ?HotelType, +index: number |}) => (
+    <AllHotelsSearchRow
+      key={item?.id}
+      data={item}
+      testID={index === 0 ? 'firstHotelResult' : ''}
+    />
+  );
+
   render() {
     const hotels = this.props.data || [];
 
@@ -37,15 +53,12 @@ export class AllHotelsSearchList extends React.Component<Props> {
     }
 
     return (
-      <React.Fragment>
-        {hotels.map((hotel, index) => (
-          <AllHotelsSearchRow
-            key={hotel?.id}
-            data={hotel}
-            testID={index === 0 ? 'firstHotelResult' : ''}
-          />
-        ))}
-      </React.Fragment>
+      <FlatList
+        keyExtractor={this.keyExtractor}
+        renderItem={this.renderItem}
+        data={this.props.data ?? []}
+        ListFooterComponent={this.props.ListFooterComponent}
+      />
     );
   }
 }
diff --git a/app/hotels/src/allHotels/RenderSearchResults.js b/app/hotels/src/allHotels/RenderSearchResults.js
index beda37e7..b2643723 100644
--- a/app/hotels/src/allHotels/RenderSearchResults.js
+++ b/app/hotels/src/allHotels/RenderSearchResults.js
@@ -1,7 +1,7 @@
 // @flow strict
 
 import * as React from 'react';
-import { Animated, ScrollView } from 'react-native';
+import { Animated, View } from 'react-native';
 import { graphql, createFragmentContainer } from '@kiwicom/mobile-relay';
 import { StyleSheet, Device } from '@kiwicom/mobile-shared';
 
@@ -91,16 +91,19 @@ export class RenderSearchResults extends React.Component<Props> {
             transform: [{ translateY: this.listAnimation }],
           }}
         >
-          {/*  Note: it's not possible to use FlatList here because it's wrapped with ScrollView and it causes performance issues.*/}
-          <ScrollView contentContainerStyle={styles.content}>
-            <AllHotelsSearchList data={data} />
-            {this.props.hasMore && (
-              <LoadMoreButton
-                isLoading={this.props.isLoading}
-                onPress={this.props.onLoadMore}
-              />
-            )}
-          </ScrollView>
+          <View style={styles.content}>
+            <AllHotelsSearchList
+              data={data}
+              ListFooterComponent={
+                this.props.hasMore && (
+                  <LoadMoreButton
+                    isLoading={this.props.isLoading}
+                    onPress={this.props.onLoadMore}
+                  />
+                )
+              }
+            />
+          </View>
         </Animated.View>
         <Animated.View
           style={{


Test patch:
diff --git a/app/hotels/src/allHotels/__tests__/AllHotelsSearchList.test.js b/app/hotels/src/allHotels/__tests__/AllHotelsSearchList.test.js
index 13df40af..b5754b40 100644
--- a/app/hotels/src/allHotels/__tests__/AllHotelsSearchList.test.js
+++ b/app/hotels/src/allHotels/__tests__/AllHotelsSearchList.test.js
@@ -10,6 +10,8 @@ const renderer = new ShallowRenderer();
 
 const $fragmentRefs: any = null;
 const $refType: any = null;
+const Footer = () => null;
+
 it('renders found hotels', () => {
   const data: AllHotelsSearchListType = [
     {
@@ -26,14 +28,26 @@ it('renders found hotels', () => {
     },
   ];
 
-  renderer.render(<AllHotelsSearchList data={data} setHotelId={jest.fn()} />);
+  renderer.render(
+    <AllHotelsSearchList
+      data={data}
+      setHotelId={jest.fn()}
+      ListFooterComponent={<Footer />}
+    />,
+  );
   expect(renderer.getRenderOutput()).toMatchSnapshot();
 });
 
 it('renders a "not found" message when no hotel is found', () => {
   const data: Array<empty> = [];
 
-  renderer.render(<AllHotelsSearchList data={data} setHotelId={jest.fn()} />);
+  renderer.render(
+    <AllHotelsSearchList
+      data={data}
+      setHotelId={jest.fn()}
+      ListFooterComponent={<Footer />}
+    />,
+  );
   expect(renderer.getRenderOutput()).toMatchSnapshot();
 });
 
diff --git a/app/hotels/src/allHotels/__tests__/__snapshots__/AllHotelsSearchList.test.js.snap b/app/hotels/src/allHotels/__tests__/__snapshots__/AllHotelsSearchList.test.js.snap
index 8807eb5f..426ce9ef 100644
--- a/app/hotels/src/allHotels/__tests__/__snapshots__/AllHotelsSearchList.test.js.snap
+++ b/app/hotels/src/allHotels/__tests__/__snapshots__/AllHotelsSearchList.test.js.snap
@@ -21,28 +21,34 @@ exports[`renders a "not found" message when no hotel is found 1`] = `
 `;
 
 exports[`renders found hotels 1`] = `
-<React.Fragment>
-  <ForwardRef(Relay(WithContext))
-    data={
+<FlatList
+  ListFooterComponent={<Footer />}
+  data={
+    Array [
       Object {
         "$fragmentRefs": null,
         "$refType": null,
         "hotelId": "lol1",
         "id": "hotel1",
-      }
-    }
-    testID="firstHotelResult"
-  />
-  <ForwardRef(Relay(WithContext))
-    data={
+      },
       Object {
         "$fragmentRefs": null,
         "$refType": null,
         "hotelId": "lol2",
         "id": "hotel2",
-      }
-    }
-    testID=""
-  />
-</React.Fragment>
+      },
+    ]
+  }
+  disableVirtualization={false}
+  horizontal={false}
+  initialNumToRender={10}
+  keyExtractor={[Function]}
+  maxToRenderPerBatch={10}
+  numColumns={1}
+  onEndReachedThreshold={2}
+  renderItem={[Function]}
+  scrollEventThrottle={50}
+  updateCellsBatchingPeriod={50}
+  windowSize={21}
+/>
 `;