React'te Sonsuz Kaydırma ve Görüntü Tembel Yükleme Uygulaması

Yayınlanan: 2022-03-10
Hızlı özet ↬ Bu eğitimde, bir React işlevsel bileşeninde sonsuz kaydırma ve görüntü gecikmeli yükleme uygulamak için HTML Intersection Observer API'sinin nasıl kullanılacağını öğreneceğiz. Bu süreçte, React'in bazı kancalarının nasıl kullanılacağını ve Özel Kancaların nasıl oluşturulacağını öğreneceğiz.

Sayfalandırmaya bir alternatif arıyorsanız, sonsuz kaydırma iyi bir fikirdir. Bu makalede, bir React işlevsel bileşeni bağlamında Intersection Observer API için bazı kullanım örneklerini keşfedeceğiz. Okuyucu, React fonksiyonel bileşenleri hakkında çalışan bir bilgiye sahip olmalıdır. Birkaçına göz atacağımız için, React kancalarına biraz aşina olmak faydalı olacaktır, ancak gerekli değildir.

Amacımız, bu makalenin sonunda, yerel bir HTML API kullanarak sonsuz kaydırma ve görüntü tembel yüklemeyi gerçekleştirmiş olmamızdır. Ayrıca React Hooks hakkında birkaç şey daha öğrenmiş olurduk. Bununla, gerektiğinde React uygulamanızda sonsuz kaydırma ve görüntü tembel yükleme uygulayabilirsiniz.

Başlayalım.

React ve Leaflet ile Harita Oluşturma

Bir CSV veya JSON dosyasından bilgi almak sadece karmaşık değil, aynı zamanda sıkıcıdır. Aynı verileri görsel yardım şeklinde temsil etmek daha basittir. Shajia Abidi, Leaflet'in ne kadar güçlü bir araç olduğunu ve birçok farklı türde haritanın nasıl oluşturulabileceğini açıklıyor. İlgili bir makaleyi okuyun →

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Kavşak Gözlemci API'sı

MDN belgelerine göre, “Kesişim Gözlemcisi API'si, bir hedef öğenin bir üst öğeyle veya bir üst düzey belgenin görünüm alanıyla kesişimindeki değişiklikleri eşzamansız olarak gözlemlemek için bir yol sağlar”.

Bu API, sonsuz kaydırma ve görüntü gecikmeli yükleme gibi harika özellikleri uygulamamıza olanak tanır. Kavşak gözlemcisi, yapıcısını çağırarak ve ona bir geri arama ve bir seçenekler nesnesi ileterek oluşturulur. target adı verilen bir öğe, aygıt görünüm alanıyla veya root adı verilen belirli bir öğeyle kesiştiğinde geri arama çağrılır. Seçenekler argümanında özel bir kök belirtebilir veya varsayılan değeri kullanabiliriz.

 let observer = new IntersectionObserver(callback, options);

API'nin kullanımı basittir. Tipik bir örnek şöyle görünür:

 var intObserver = new IntersectionObserver(entries => { entries.forEach(entry => { console.log(entry) console.log(entry.isIntersecting) // returns true if the target intersects the root element }) }, { // default options } ); let target = document.querySelector('#targetId'); intObserver.observe(target); // start observation

entries , IntersectionObserverEntry nesnelerinin bir listesidir. IntersectionObserverEntry nesnesi, gözlemlenen bir hedef öğe için bir kesişim değişikliğini tanımlar. Geri aramanın, ana iş parçacığında çalıştığı için zaman alan herhangi bir görevi yerine getirmemesi gerektiğini unutmayın.

Intersection Observer API, caniuse'da gösterildiği gibi şu anda geniş tarayıcı desteğine sahiptir.

Kavşak Gözlemcisi tarayıcı desteği. (Büyük önizleme)

API hakkında daha fazla bilgiyi kaynaklar bölümünde sağlanan bağlantılardan okuyabilirsiniz.

Şimdi bu API'yi gerçek bir React uygulamasında nasıl kullanabileceğimize bakalım. Uygulamamızın son versiyonu, sonsuz kaydırılan ve her bir resmin tembelce yüklendiği bir resim sayfası olacaktır.

useEffect Hook ile API Çağrıları Yapma

Başlamak için başlangıç ​​projesini bu URL'den kopyalayın. Minimum kurulum ve tanımlanmış birkaç stile sahiptir. Ayrıca, sınıflarını stil için kullanacağım için public/index.html dosyasına Bootstrap bir bağlantı ekledim.

İsterseniz yeni bir proje oluşturmaktan çekinmeyin. Repo ile takip etmek istiyorsanız yarn paket yöneticisinin kurulu olduğundan emin olun. Özel işletim sisteminiz için kurulum talimatlarını burada bulabilirsiniz.

Bu eğitim için, genel bir API'den resimler alıp sayfada görüntüleyeceğiz. Lorem Picsum API'lerini kullanacağız.

Bu eğitim için, bir dizi resim nesnesi döndüren https://picsum.photos/v2/list?page=0&limit=10 bitiş noktasını kullanacağız. Sonraki on resmi almak için sayfanın değerini 1, ardından 2 vb. olarak değiştiririz.

Şimdi Uygulama bileşenini parça parça oluşturacağız.

src/App.js açın ve aşağıdaki kodu girin.

 import React, { useEffect, useReducer } from 'react'; import './index.css'; function App() { const imgReducer = (state, action) => { switch (action.type) { case 'STACK_IMAGES': return { ...state, images: state.images.concat(action.images) } case 'FETCHING_IMAGES': return { ...state, fetching: action.fetching } default: return state; } } const [imgData, imgDispatch] = useReducer(imgReducer,{ images:[], fetching: true}) // next code block goes here }

İlk olarak, bir redüktör işlevi tanımlıyoruz, imgReducer . Bu redüktör iki eylemi gerçekleştirir.

  1. STACK_IMAGES eylemi, images dizisini birleştirir.
  2. FETCHING_IMAGES eylemi, fetching değişkeninin değerini true ve false arasında değiştirir.

Bir sonraki adım, bu redüktörü bir useReducer kancasına bağlamaktır. Bu yapıldıktan sonra, iki şeyi geri alırız:

  1. imgData , iki değişken içerir: images , resim nesneleri dizisidir. fetching , API çağrısının devam edip etmediğini bize söyleyen bir booledir.
  2. redüktör nesnesini güncellemek için bir işlev olan imgDispatch .

React belgelerinde useReducer kancası hakkında daha fazla bilgi edinebilirsiniz.

Kodun sonraki kısmı, API çağrısını yaptığımız yerdir. Aşağıdaki kodu App.js önceki kod bloğunun altına yapıştırın.

 // make API calls useEffect(() => { imgDispatch({ type: 'FETCHING_IMAGES', fetching: true }) fetch('https://picsum.photos/v2/list?page=0&limit=10') .then(data => data.json()) .then(images => { imgDispatch({ type: 'STACK_IMAGES', images }) imgDispatch({ type: 'FETCHING_IMAGES', fetching: false }) }) .catch(e => { // handle error imgDispatch({ type: 'FETCHING_IMAGES', fetching: false }) return e }) }, [ imgDispatch ]) // next code block goes here

useEffect kancasının içinde, fetch API'si ile API uç noktasına bir çağrı yaparız. Ardından, STACK_IMAGES eylemini göndererek, API çağrısının sonucuyla görüntüler dizisini güncelleriz. API çağrısı tamamlandıktan sonra FETCHING_IMAGES eylemini de göndeririz.

Sonraki kod bloğu, işlevin dönüş değerini tanımlar. useEffect kancasından sonra aşağıdaki kodu girin.

 return ( <div className=""> <nav className="navbar bg-light"> <div className="container"> <a className="navbar-brand" href="/#"> <h2>Infinite scroll + image lazy loading</h2> </a> </div> </navv <div id='images' className="container"> <div className="row"> {imgData.images.map((image, index) => { const { author, download_url } = image return ( <div key={index} className="card"> <div className="card-body "> <img alt={author} className="card-img-top" src={download_url} /> </div> <div className="card-footer"> <p className="card-text text-center text-capitalize text-primary">Shot by: {author}</p> </div> </div> ) })} </div> </div> </div> );

Görüntüleri görüntülemek için, imgData nesnesindeki görüntüler dizisi üzerinde eşleniriz.

Şimdi uygulamayı başlatın ve sayfayı tarayıcıda görüntüleyin. Duyarlı bir ızgarada güzel bir şekilde görüntülenen görüntüleri görmelisiniz.

Son bit, Uygulama bileşenini dışa aktarmaktır.

 export default App;
Duyarlı kılavuzdaki resimler. (Büyük önizleme)

Bu noktada karşılık gelen dal 01-make-api-calls'dır.

Şimdi sayfa kaydırılırken daha fazla resim görüntüleyerek bunu genişletelim.

Sonsuz Kaydırma Uygulaması

Sayfa ilerledikçe daha fazla resim sunmayı amaçlıyoruz. API uç noktasının URL'sinden, https://picsum.photos/v2/list?page=0&limit=10 , yeni bir fotoğraf grubu elde etmek için yalnızca page değerini artırmamız gerektiğini biliyoruz. Gösterecek resimlerimiz bittiğinde de bunu yapmamız gerekiyor. Buradaki amacımız için sayfanın en altına geldiğimizde resimlerin bittiğini anlayacağız. Intersection Observer API'sinin bunu başarmamıza nasıl yardımcı olduğunu görmenin zamanı geldi.

src/App.js açın ve imgReducer altında yeni bir redüktör, pageReducer imgReducer .

 // App.js const imgReducer = (state, action) => { ... } const pageReducer = (state, action) => { switch (action.type) { case 'ADVANCE_PAGE': return { ...state, page: state.page + 1 } default: return state; } } const [ pager, pagerDispatch ] = useReducer(pageReducer, { page: 0 })

Sadece bir eylem tipi tanımlıyoruz. ADVANCE_PAGE eylemi her tetiklendiğinde, page değeri 1 artırılır.

Aşağıda gösterildiği gibi sayfa numaralarını dinamik olarak kabul etmek için fetch işlevindeki URL'yi güncelleyin.

 fetch(`https://picsum.photos/v2/list?page=${pager.page}&limit=10`)

pager.page ile birlikte bağımlılık dizisine imgData . Bunu yapmak, pager.page her değiştiğinde API çağrısının çalışmasını sağlar.

 useEffect(() => { ... }, [ imgDispatch, pager.page ])

API çağrısı için useEffect kancasından sonra aşağıdaki kodu girin. İçe aktarma satırınızı da güncelleyin.

 // App.js import React, { useEffect, useReducer, useCallback, useRef } from 'react'; useEffect(() => { ... }, [ imgDispatch, pager.page ]) // implement infinite scrolling with intersection observer let bottomBoundaryRef = useRef(null); const scrollObserver = useCallback( node => { new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { pagerDispatch({ type: 'ADVANCE_PAGE' }); } }); }).observe(node); }, [pagerDispatch] ); useEffect(() => { if (bottomBoundaryRef.current) { scrollObserver(bottomBoundaryRef.current); } }, [scrollObserver, bottomBoundaryRef]);

Bir bottomBoundaryRef değişkeni tanımlıyoruz ve değerini useRef(null) olarak ayarlıyoruz. useRef , değişkenlerin bileşen oluşturma işlemleri boyunca değerlerini korumasına izin verir, yani, içeren bileşen yeniden oluşturulduğunda değişkenin geçerli değeri devam eder. Değerini değiştirmenin tek yolu, o değişkene .current özelliğini yeniden atamaktır.

Bizim durumumuzda, bottomBoundaryRef.current değeri null ile başlar. Sayfa oluşturma döngüsü ilerledikçe, mevcut özelliğini <div id='page-bottom-boundary'> düğümü olarak ayarladık.

React'e bu atamanın bildirildiği div olarak bottomBoundaryRef.current ayarlamasını söylemek için ref={bottomBoundaryRef} atama ifadesini kullanırız.

Böylece,

 bottomBoundaryRef.current = null

işleme döngüsünün sonunda şu hale gelir:

 bottomBoundaryRef.current = <div></div>

Bu atamanın nerede yapıldığını birazdan göreceğiz.

Ardından, gözlemcinin ayarlanacağı bir scrollObserver işlevi tanımlarız. Bu işlev, gözlemlenecek bir DOM düğümünü kabul eder. Burada dikkat edilmesi gereken en önemli nokta, gözlem altındaki kavşağa her geldiğimizde ADVANCE_PAGE eylemini göndermemizdir. Efekt, pager.page değerini 1 arttırmaktır. Bu gerçekleştiğinde, onu bir bağımlılık olarak içeren useEffect kancası yeniden çalıştırılır. Bu yeniden çalıştırma, sırayla, yeni sayfa numarasıyla getirme çağrısını başlatır.

Etkinlik alayı böyle görünüyor.

Gözlem altındaki kesişme noktasına basın → ADVANCE_PAGE eylemini çağırın → pager.page değerini 1 artır → getirme çağrısı çalıştırmaları için useEffect kancası → fetch çağrısı çalıştırılıyor → döndürülen görüntüler, images dizisine birleştirilir.

Bir useEffect kancasında scrollObserver , böylece işlev yalnızca kancanın bağımlılıklarından herhangi biri değiştiğinde çalışır. Bir useEffect kancasının içindeki işlevi çağırmasaydık, işlev her sayfa oluşturma işleminde çalışırdı.

bottomBoundaryRef.current <div id="page-bottom-boundary" style="border: 1px solid red;"></div> öğesine atıfta bulunduğunu hatırlayın. scrollObserver geçirmeden önce değerinin null olmadığını kontrol ederiz. Aksi takdirde, IntersectionObserver yapıcısı bir hata döndürür.

Bir useEffect kancasında scrollObserver kullandığımız için, bitmeyen bileşen yeniden oluşturmalarını önlemek için onu bir useCallback kancasına sarmamız gerekir. React belgelerinde useCallback hakkında daha fazla bilgi edinebilirsiniz.

<div id='images'> div'den sonra aşağıdaki kodu girin.

 // App.js <div id='image'> ... </div> {imgData.fetching && ( <div className="text-center bg-secondary m-auto p-3"> <p className="m-0 text-white">Getting images</p> </div> )} <div id='page-bottom-boundary' style={{ border: '1px solid red' }} ref={bottomBoundaryRef}></div>

API çağrısı başladığında, getirmeyi true olarak ayarladık ve Görüntüler fetching metni görünür hale gelir. fetching , getirmeyi false olarak ayarladık ve metin gizlendi. Ayrıca, yapıcı seçenekleri nesnesinde farklı bir threshold ayarlayarak tam olarak sınıra ulaşmadan önce API çağrısını tetikleyebiliriz. Sondaki kırmızı çizgi, sayfa sınırına tam olarak ne zaman ulaştığımızı görmemizi sağlar.

Bu noktada karşılık gelen dal 02-sonsuz kaydırmadır.

Şimdi görüntü tembel yükleme uygulayacağız.

Görüntü Tembel Yüklemeyi Uygulama

Aşağı kaydırırken ağ sekmesini incelerseniz, kırmızı çizgiye (alt sınıra) basar basmaz API çağrısının gerçekleştiğini ve görüntülemeye başlamamış olsanız bile tüm resimlerin yüklenmeye başladığını görürsünüz. onlara. Bunun arzu edilen bir davranış olmamasının çeşitli nedenleri vardır. Kullanıcı bir resim görmek isteyene kadar şebeke aramalarını kaydetmek isteyebiliriz. Böyle bir durumda, görüntüleri tembelce yüklemeyi seçebiliriz, yani, görüntü kayan hale gelene kadar bir görüntü yüklemeyeceğiz.

src/App.js açın. Sonsuz kaydırma fonksiyonlarının hemen altına aşağıdaki kodu girin.

 // App.js // lazy loads images with intersection observer // only swap out the image source if the new url exists const imagesRef = useRef(null); const imgObserver = useCallback(node => { const intObs = new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { const currentImg = en.target; const newImgSrc = currentImg.dataset.src; // only swap out the image source if the new url exists if (!newImgSrc) { console.error('Image source is invalid'); } else { currentImg.src = newImgSrc; } intObs.unobserve(node); // detach the observer when done } }); }) intObs.observe(node); }, []); useEffect(() => { imagesRef.current = document.querySelectorAll('.card-img-top'); if (imagesRef.current) { imagesRef.current.forEach(img => imgObserver(img)); } }, [imgObserver, imagesRef, imgData.images]);

scrollObserver olduğu gibi, gözlemlenecek bir düğümü kabul eden imgObserver adlı bir işlev tanımlarız. Sayfa, en.intersectionRatio > 0 tarafından belirlendiği gibi bir kesişmeye çarptığında, öğe üzerindeki görüntü kaynağını değiştiririz. Takas yapmadan önce yeni görüntü kaynağının var olup olmadığını kontrol ettiğimize dikkat edin. scrollObserver işlevinde olduğu gibi, bitmeyen bileşen yeniden oluşturmayı önlemek için imgObserver'ı bir useCallback kancasına sarıyoruz.

Ayrıca, ikame işlemini bitirdiğimizde bir img öğesini gözlemlemeyi bıraktığımızı da unutmayın. Bunu unobserve yöntemiyle yapıyoruz.

Aşağıdaki useEffect kancasında, .card-img-top sınıfına sahip tüm görüntüleri document.querySelectorAll ile alıyoruz. Daha sonra her görüntü üzerinde yinelenir ve üzerine bir gözlemci yerleştiririz.

imgData.images useEffect kancasının bir bağımlılığı olarak eklediğimizi unutmayın. Bu değiştiğinde useEffect kancasını tetikler ve sırayla her <img className='card-img-top'> öğesiyle imgObserver çağrılır.

<img className='card-img-top'/> öğesini aşağıda gösterildiği gibi güncelleyin.

 <img alt={author} data-src={download_url} className="card-img-top" src={'https://picsum.photos/id/870/300/300?grayscale&blur=2'} />

Her <img className='card-img-top'/> öğesi için varsayılan bir kaynak belirledik ve göstermek istediğimiz görüntüyü data-src özelliğinde saklıyoruz. Varsayılan resim genellikle küçük bir boyuta sahiptir, bu nedenle mümkün olduğunca az indiriyoruz. <img/> öğesi görüntülendiğinde, data-src özelliğindeki değer varsayılan görüntünün yerini alır.

Aşağıdaki resimde, bazı alanlarda hala gösterilen varsayılan deniz feneri görüntüsünü görüyoruz.

Resimler tembelce yükleniyor. (Büyük önizleme)

Bu noktada karşılık gelen dal 03 tembel yüklemedir.

Şimdi tüm bu fonksiyonları yeniden kullanılabilir hale getirmek için nasıl soyutlayacağımızı görelim.

Soyutlama Getirme, Sonsuz Kaydırma ve Özel Kancalara Tembel Yükleme

Getirme, sonsuz kaydırma ve görüntü gecikmeli yüklemeyi başarıyla uyguladık. Uygulamamızda benzer işlevselliğe ihtiyaç duyan başka bir bileşenimiz olabilir. Bu durumda, bu fonksiyonları soyutlayabilir ve yeniden kullanabiliriz. Tek yapmamız gereken onları ayrı bir dosyaya taşımak ve ihtiyacımız olan yere aktarmak. Bunları Özel Kancalara dönüştürmek istiyoruz.

React belgeleri, Özel Kancayı, adı "use" ile başlayan ve diğer kancaları çağırabilen bir JavaScript işlevi olarak tanımlar. Bizim durumumuzda, useFetch , useInfiniteScroll , useLazyLoading olmak üzere üç kanca oluşturmak istiyoruz.

src/ klasörü içinde bir dosya oluşturun. customHooks.js olarak adlandırın ve aşağıdaki kodu içine yapıştırın.

 // customHooks.js import { useEffect, useCallback, useRef } from 'react'; // make API calls and pass the returned data via dispatch export const useFetch = (data, dispatch) => { useEffect(() => { dispatch({ type: 'FETCHING_IMAGES', fetching: true }); fetch(`https://picsum.photos/v2/list?page=${data.page}&limit=10`) .then(data => data.json()) .then(images => { dispatch({ type: 'STACK_IMAGES', images }); dispatch({ type: 'FETCHING_IMAGES', fetching: false }); }) .catch(e => { dispatch({ type: 'FETCHING_IMAGES', fetching: false }); return e; }) }, [dispatch, data.page]) } // next code block here

useFetch kancası, bir gönderme işlevini ve bir veri nesnesini kabul eder. Gönderme işlevi, API çağrısından gelen verileri App bileşenine iletir, veri nesnesi ise API uç noktası URL'sini güncellememize izin verir.

 // infinite scrolling with intersection observer export const useInfiniteScroll = (scrollRef, dispatch) => { const scrollObserver = useCallback( node => { new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { dispatch({ type: 'ADVANCE_PAGE' }); } }); }).observe(node); }, [dispatch] ); useEffect(() => { if (scrollRef.current) { scrollObserver(scrollRef.current); } }, [scrollObserver, scrollRef]); } // next code block here

useInfiniteScroll kancası, bir scrollRef ve bir dispatch işlevini kabul eder. scrollRef , uyguladığımız bölümde daha önce tartışıldığı gibi, gözlemciyi kurmamıza yardımcı olur. Gönderme işlevi, API bitiş noktası URL'sindeki sayfa numarasını güncelleyen bir eylemi tetiklemenin bir yolunu sunar.

 // lazy load images with intersection observer export const useLazyLoading = (imgSelector, items) => { const imgObserver = useCallback(node => { const intObs = new IntersectionObserver(entries => { entries.forEach(en => { if (en.intersectionRatio > 0) { const currentImg = en.target; const newImgSrc = currentImg.dataset.src; // only swap out the image source if the new url exists if (!newImgSrc) { console.error('Image source is invalid'); } else { currentImg.src = newImgSrc; } intObs.unobserve(node); // detach the observer when done } }); }) intObs.observe(node); }, []); const imagesRef = useRef(null); useEffect(() => { imagesRef.current = document.querySelectorAll(imgSelector); if (imagesRef.current) { imagesRef.current.forEach(img => imgObserver(img)); } }, [imgObserver, imagesRef, imgSelector, items]) }

useLazyLoading kancası bir seçici ve bir dizi alır. Seçici, görüntüleri bulmak için kullanılır. Dizideki herhangi bir değişiklik, her görüntüde gözlemciyi ayarlayan useEffect kancasını tetikler.

Yeni bir dosyaya çıkardığımızın src/App.js sahip olduğumuz işlevlerin aynısı olduğunu görebiliriz. Şimdi iyi olan şey, argümanları dinamik olarak iletebilmemiz. Şimdi bu özel kancaları Uygulama bileşeninde kullanalım.

src/App.js açın. Özel kancaları içe aktarın ve veri getirme, sonsuz kaydırma ve görüntü gecikmeli yükleme için tanımladığımız işlevleri silin. Redüktörleri ve useReducer kullandığımız bölümleri bırakın. Aşağıdaki kodu yapıştırın.

 // App.js // import custom hooks import { useFetch, useInfiniteScroll, useLazyLoading } from './customHooks' const imgReducer = (state, action) => { ... } // retain this const pageReducer = (state, action) => { ... } // retain this const [pager, pagerDispatch] = useReducer(pageReducer, { page: 0 }) // retain this const [imgData, imgDispatch] = useReducer(imgReducer,{ images:[], fetching: true }) // retain this let bottomBoundaryRef = useRef(null); useFetch(pager, imgDispatch); useLazyLoading('.card-img-top', imgData.images) useInfiniteScroll(bottomBoundaryRef, pagerDispatch); // retain the return block return ( ... )

Sonsuz kaydırma ile ilgili bölümde bottomBoundaryRef hakkında zaten konuşmuştuk. pager nesnesini ve imgDispatch işlevini useFetch . useLazyLoading .card-img-top sınıf adını kabul eder. not edin . sınıf adına dahil edilmiştir. Bunu yaparak, bunu belirtmemize gerek yok document.querySelectorAll . useInfiniteScroll , page değerini artırmak için hem bir başvuru hem de gönderme işlevini kabul eder.

Bu noktada karşılık gelen dal 04-özel kancadır.

Çözüm

HTML, harika özellikleri uygulamak için güzel API'ler sağlamada daha iyi hale geliyor. Bu yazıda, bir React fonksiyonel bileşeninde kesişim gözlemcisini kullanmanın ne kadar kolay olduğunu gördük. Bu süreçte, React'in bazı kancalarını nasıl kullanacağımızı ve kendi kancalarımızı nasıl yazacağımızı öğrendik.

Kaynaklar

  • "Sonsuz Kaydırma + Görüntü Tembel Yükleme", Orji Chidi Matthew, GitHub
  • “Sonsuz Kaydırma, Sayfalandırma veya “Daha Fazla Yükle” Düğmeleri? E-Ticarette Kullanılabilirlik Bulguları,” Christian Holst, Smashing Magazine
  • “Lorem Picsum,” David Marby ve Nijiko Yonskai
  • “IntersectionObserver Görüntülenmeye Geliyor,” Surma, Web Fundamentals
  • Kullanabilir miyim… IntersectionObserver
  • "Kesişim Gözlemcisi API'si", MDN web belgeleri
  • "Bileşenler ve Aksesuarlar", React
  • " useCallback ," Tepki
  • " useReducer ," Tepki