React Native’de FlatList İle Infinite Scroll Nasıl Yapılır?
Bu yazının demo projesi GitHub’da bulunmaktadır — Demo projesinin bulunduğu GitHub Reposu → Repo
Bir uygulama geliştirirken, bu web veya mobil olabilir, elimizde birçok içerik/veri bulunduğunda bunları tek seferde kullanıcıya göstermek hem kullanıcının izlenimi açısından hem de uygulamayı kullanırken alacağı performans açısından negatif bir etki oluşturabilir. Bu yüzden genellikle elimizde çok fazla sayıda veri olduğunda hepsini tek seferde göstermektense bunların parçalar halinde gösterilmesi tercih edilir. İçeriklerin parçalar halinde gösterimini pagination veya Infinite scroll dediğimiz tekniği/konsepti kullanarak gerçekleştirebiliriz. Yazının konusundan sapmamak adına bu tekniklerin ne zaman seçilmesi gerektiği konusuna çok girmek istemiyorum. Dilerseniz ufak bir araştırma yapıp bunlar hakkında yazılmış olan makaleleri inceleyebilirsiniz. Ben bu yazıda Infinite Scroll tekniğini ele alıyor olacağım :)
Infinite Scroll Nedir ?
Infinite Scroll, yeni verileri görebilmek için sayfalamaya yani pagination’a gerek duymaksızın biz sayfayı kaydırdıkça yeni verilerin yüklenmesidir.
Bugün yapacağım uygulamada FlatList kullanarak bunu nasıl gerçekleştirebiliriz bakalım :)
FlatList Nedir ?
FlatList, elinizdeki verileri verimli bir şekilde listelemenizi sağlayan bir react-native componentidir. Verimli şekilde diyorum çünkü buna benzer olarak kullanılan Scrollview’e bakacak olursak eğer:
ScrollView
renders all its react child components at once, but this has a performance downside.
Scrollview, component’iniz ekranda gözükmeye başladığı andan itibaren elinizde olan tüm verileri RAM’e yükler. Elimizde 100 veya 1000 tane veri olduğunu ve bunların tek seferde RAM’de tutulduğunu düşünürsek eğer, tahmin edebileceğiniz gibi uygulamanın performans açısından yavaşlamasına sebep olur.
FlatList’in arkasında ise VirtualizedList componenti çalışmaktadır.
VirtualizedList component’inde ise virtualized list tekniği/konsepti kullanılarak, ekranda sadece gözüken elemanların render edilmesi sağlanır.
Bunun yanında FlatList, içerisinde pek çok özellik bulundurmaktadır. Sahip olduğu özelliklere şuradan inceleyebilirsiniz. Ben de yapacağımız demoda birkaç tanesini göstermeye çalışacağım.
Bugün göstereceğim örnekte Pixabay sitesinden çekeceğimiz görsellerin listelemesini yapalım. Sayfayı kaydırdıkça yeni görsellerin yüklenmesini sağlayalım. Demo görüntüsünü Ekleyeyim :)
Demo
Proje Kurulumu
Öncelikle bir react native projesi oluşturalım. Bunun için:
npx react-native init <proje_adi>
Projemiz hazır olduğunda, proje klasörüne gidelim ve Pixabay servislerine istekte bulunabilmek için kullanacağımız axios kütüphanesini yükleyelim.
npm install axios
Pixabay’ın sağlamış olduğu servisleri kullanabilmemiz için elinizde bir api key olması gerekmektedir. Siteye kayıt olarak api key’inizi alabilirsiniz.
Bu örneğimizde uygulamamızda bulunan App.js dosyası üzerinden işlemlerimi gerçekleştireceğim.
Projeyi oluşturduğumuz zaman App component’i bizim için fonksiyon türünde bir component olarak karşımıza çıkar. Fonksiyon componentlerinde state kullanımı veya servise istekte bulunmak için hooks özelliğinden faydalanabiliriz. Ancak bu yazıda hooks’a girmemek adına, App Componentini sınıf componentine dönüştüreceğim.
Öncelik servise istekte bulunduktan sonra gelen listeyi kaydedebilmemiz için constructor içerisinde bir list state’i tanımlayalım.
Şimdi Pixabay’a görseller için bir istek atalım ve gelen veri listesini, tanımlamış olduğumuz list state’ine aktaralım.
Class türündeki bir React componentinin yaşam döngülerinden biri olan componentDidMount ile, bu component sayfada belirdiği zaman (mounted) neler yapılması gerektiğini belirtiriz. Çağırmış olduğumuz bu serviste dönen response’un içerisinde gelen görsel listesini alıp kendi state’imize aktaralım.
Şimdi bu listeyi Flatlist’e aktaralım ve listemizde bulunan görsellerin ekranda gösterilmesini sağlayalım.
Kullandığımız props’lara bakalım.
data: render edilmesi istenen listeyi içerir.
renderItem: Her bir liste elemanın render edilmesi sağlanır. Her liste elemanı için bir PreviewImage compenenti oluşturulur. PreviewImage componentine, liste elemanına ait bilgileri aktarırız ve Image componentine de görselin sahip olduğu url’i aktararak ekranda gösterilmesini sağlarız.
Resimlerin gösterimini sağlamamıza rağmen ekranda bir uyarı bulunuyor. O da ne ? 🤔
Hatayı aynı şekilde uygulamadan Debug modunu açtığımızda, tarayıcının konsol sekmesinden de görebiliriz.
Burada bize, liste elemanlarında key değerlerinin eksik olduğu belirtiliyor. FlatList’in keyExtractor özelliğini kullanabiliriz.
keyExtractor ile FlatList’in liste ögelerini takip etmesi ve listenin verimli şekilde render edilmesini sağlamak için kullanılır. Her bir elemanın keyExtractor değeri benzersiz (unique) olması gerektiği için elemanın id değerini verebiliriz.
Artık Infinite Scroll özelliğimizi ekleyebiliriizz :).
Şimdi yeni görselleri Pixabay’ın diğer sayfalarında getirebilmek için page adında yeni bir state ekleyelim. Listenin son elemanına geldiğimiz zaman page değerini 1 artırarak tekrar pixabay servisimize istekte bulunalım ve diğer sayfaya ait görsellerin yüklenmesini sağlayalım.
getImages() metodumuzu buna göre düzenleyelim:
Yukarıda query’imize page state’inide ekledik. Böylelikle page değerine göre o sayfadaki görsellerin getirilmesini sağlarız.
Bir diğer yaptığımız değişiklik ise setState içerisinde eğer ilk sayfanın değerlerini almışsak gelen veriyi direkt olarak list state’imize atayabiliriz. Ama bir sonraki sayfanın verilerini de getirdiğimiz zaman, bir önceki liste ögelerini elimizde tutup, yeni gelen verileride elimizdeki listeye aktarabilmemiz için ES6'nın bize sağlamış olduğu spread operator’ünü kullanabiliriz. Burada kullandığımız spread operatörü ile “Git list state’ine ait değelerleri al. Bunları aldıktan sonra da yaptığın istekten dönen liste elemanlarını da al ve list state’ine ata.” demiş oluruz. Böylelikle hem bir önceki verileri elimizde tutmuş oluruz hem de yeni gelen görselleri bu listeye eklemiş oluruz.
onEndReached
Listede en alttaki elemana geldiğimiz zaman yeni görsellerin gelme işlemini tetikleyebilmek için FlatList’in onEndReached özelliğinden faydalanabiliriz.
onEndReached içerisine getMoreImages adlı bir metod’u referans verdik. Böylelikle listenin sonuna ulaştığımızda, getMoreImages metodu tetikleniyor olacak. getMoreImages metodu içerisinde de diğer sayfaya ait görselleri almak istediğimiz için page değerini 1 artırıyoruz. Bu işlemi gerçekleştirden sonra getImages ile servis’imizin tekrar tetiklenmesini sağlıyoruz.
Loading Indicator
Her şey harika! Ancak bir eksiğimiz var. O da kullanıcı gerçekten yeni verilerin gelip gelmediğini bu şekilde anlayamıyor. Bu yüzden listenin altına bir loading ikonu koyalım ve yeni veriler gelene kadar o ikonun gösterilmesini sağlayarak kullanıcıya arka tarafta işlemler gerçekleştirdiğini göstermiş olalım.
Bunun için öncelikle loading adında yeni bir state ekleyelim.
getImage metodumuz çalışmaya başladığı anda loading’i true yaparak loading ikonumuzun gösterilmesini sağlarız. Servisten response aldığımız zamanda loading değerini false yaparak gösterilmesini durdururuz.
footerIndicator ile loading state’i true ise loading ikonumuzun gösterilmesini sağlarız değilse null döndürerek gösterilmesi durdurulur.
ListFooterComponent
Listenin sonunda bunu gösterebilmemiz içinse FlatList’in ListFooterComponent özelliğinden faydalanarız. this.footerIndicator metodunu referans vererek listenin en sonunda bu metodun çalışmasını ve component’imizin gösterilmesini sağlamış oluruz.
onEndReachedThreshold
Son olarak, dilerseniz kullanıcı daha son liste elemanına gelmeden method tetiklenmesini de sağlayabilirsiniz. Bunun için FlatList’in özellikleri arasında bulunan onEndReachedThreshold’u kullanabiliriz.
Açıkçası buradaki değerin neye göre çalıştığını tam anlamadım ama okuduğum bir yazıda şu şekilde bir açıklaması bulunuyor. Buradaki 0.5 değerinin anlamı, eğer siz ekranda 8 tane veri gösteriyorsanız ve kullanıcının listenin sonuna gelmesi için 4 eleman kaldıysa getMoreImages metodumuzun tetiklenmesi sağlanır. Yani siz servis metodunuzu dilerseniz kullanıcı son liste elemanına geldiğinde tetikleyebilirsiniz veya listenin belirli bir noktasına ulaştığı andan itibaren metodu çağırma işlemini gerçekleştirebilirsiniz.
Gördüğünüz gibi daha listenin sonuna gelmeden metodumuzun tetiklenmesini sağlayarak yeni görsellerin getirilmesini sağlamış olduk :)
Phew! Böylelikle demo projemizin de sonuna gelmiş olduk 🥳🥳
Demo kodlarının bulunduğu GitHub Reposu → Repo
FlatList performansını nasıl artırabileceğiniz ile ilgili şu yazıyı da inceleyebilirsiniz.
Umarım faydalı bir yazı olmuştur. Eksik veya yanlış olduğunu düşündüğünüz kısımları bana iletirseniz çok sevinirim.
İletişim kanalları: Twitter — LinkedIn — Mail
Bir sonraki yazıda görüşmek üzere!
Bu yazının referansları:
https://stackoverflow.com/questions/55256221/flatlist-vs-scrollview/55256341
https://reactnative.dev/docs/flatlist
https://reactnative.dev/docs/optimizing-flatlist-configuration