Poprawa wydajności ScrollView – infinite scroll


Jak wiemy z dokumentacji React Native, ScrollView renderuje wszystkie swoje dzieci na raz, co przy dużej ich ilości może powodować problemy z wydajnością. Istnieje jednak sposób, by rozłożyć renderowanie dużej ilości danych w czasie tak, aby użytkownik nie odczuł tych problemów. Możemy wyświetlić przykładowo 20 elementów przy pierwszym wczytaniu danych i dodawać kolejno nowe elementy w miarę przewijania listy. Tak stworzymy „niekończące się” przewijanie, tzw. „infnite scroll”.

Implementing infinite scrolling on React Native’s scrollview

W tym wpisie: Renderowanie listy elementów za pomocą ScrollView i FlatList stworzyliśmy listę elementów za pomocą ScrollView. Teraz trzeba dodać do niej warunek, który wyświetli odpowiednią ilość zadań na ekranie. Zacznijmy od ustalenia początkowej ilości renderowanych zadań, niech będzie to 20. Zatem w stanie komponentu wartości itemToRender przypiszemy liczbę 20.

this.state = {
    itemToRender: 20,
    data: this.data,
}

Następnie wyświetlenie każdego elementu listy uzależnimy od warunku:

const item = this.state.data.map( (item, index) => {
    if (index+1 <= this.state.itemToRender) {
       return ...
    }
})

Na koniec w ScrollView dodamy warunek, po spełnieniu którego ilość wyświetlanych danych będzie się zwiększać. Niech tym warunkiem będzie dotarcie paska przewijania na wysokość listy pomniejszoną o 50. Jednak skąd mamy wiedzieć, że lista została w całości przewinięta? Musimy napisać swój własny warunek sprawdzający, coś w stylu „scroll to bottom”.

<ScrollView 
  contentContainerStyle={{paddingBottom: 70}}
  onMomentumScrollEnd={(e) => { 
     const scrollPosition = e.nativeEvent.contentOffset.y;
     const scrolViewHeight = e.nativeEvent.layoutMeasurement.height;
     const contentHeight = e.nativeEvent.contentSize.height;
     const isScrolledToBottom = scrolViewHeight + scrollPosition
     // check if scrollView is scrolled to bottom and limit itemToRender to data length
     if (isScrolledToBottom >= (contentHeight-50) && this.state.itemToRender <= this.state.data.length ) {
         this.setState({ itemToRender: this.state.itemToRender + 20 })
     }
  }}
>

Teraz po włączeniu naszej aplikacji wyrenderuje ona tylko 20 zadań (co znacznie skróci czas ładowania danych), a kolejne zadania renderować będzie dopiero po przewinięciu paska przewijania prawie do końca. Efekt:

Joanna

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *