Implementierung von Infinite Scroll und Image Lazy Loading in React
Veröffentlicht: 2022-03-10HTML
Intersection Observer
API verwendet, um unendliches Scrollen und verzögertes Laden von Bildern in einer React-Funktionskomponente zu implementieren. Dabei lernen wir, wie man einige der Hooks von React verwendet und wie man benutzerdefinierte Hooks erstellt.Wenn Sie nach einer Alternative zur Paginierung gesucht haben, ist unendliches Scrollen eine gute Überlegung. In diesem Artikel werden wir einige Anwendungsfälle für die Intersection Observer API im Kontext einer React-Funktionskomponente untersuchen. Der Leser sollte über praktische Kenntnisse der Funktionskomponenten von React verfügen. Eine gewisse Vertrautheit mit React-Hooks ist von Vorteil, aber nicht erforderlich, da wir uns einige ansehen werden.
Unser Ziel ist es, dass wir am Ende dieses Artikels unendliches Scrollen und verzögertes Laden von Bildern mithilfe einer nativen HTML-API implementiert haben. Wir hätten auch noch ein paar Dinge über React Hooks gelernt. Damit können Sie bei Bedarf unendliches Scrollen und verzögertes Laden von Bildern in Ihrer React-Anwendung implementieren.
Lass uns anfangen.
Erstellen von Karten mit React und Leaflet
Das Erfassen von Informationen aus einer CSV- oder einer JSON-Datei ist nicht nur kompliziert, sondern auch mühsam. Die Darstellung derselben Daten in Form einer visuellen Hilfe ist einfacher. Shajia Abidi erklärt, wie leistungsfähig ein Tool Leaflet ist und wie viele verschiedene Arten von Karten erstellt werden können. Lesen Sie einen verwandten Artikel →
Die Intersection Observer API
Gemäß den MDN-Dokumenten „bietet die Intersection Observer API eine Möglichkeit, Änderungen an der Überschneidung eines Zielelements mit einem Vorfahrenelement oder mit dem Ansichtsfenster eines Dokuments der obersten Ebene asynchron zu beobachten“.
Diese API ermöglicht es uns, coole Funktionen wie unendliches Scrollen und verzögertes Laden von Bildern zu implementieren. Der Schnittmengenbeobachter wird erstellt, indem sein Konstruktor aufgerufen und ihm ein Callback und ein Optionsobjekt übergeben werden. Der Rückruf wird immer dann aufgerufen, wenn ein Element, das als target
bezeichnet wird, entweder den Anzeigebereich des Geräts oder ein bestimmtes Element, das als root
bezeichnet wird, schneidet. Wir können einen benutzerdefinierten Stamm im Optionsargument angeben oder den Standardwert verwenden.
let observer = new IntersectionObserver(callback, options);
Die API ist einfach zu bedienen. Ein typisches Beispiel sieht so aus:
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
ist eine Liste von IntersectionObserverEntry
Objekten. Das IntersectionObserverEntry
-Objekt beschreibt eine Schnittpunktänderung für ein beobachtetes Zielelement. Beachten Sie, dass der Rückruf keine zeitaufwändigen Aufgaben verarbeiten sollte, da er im Hauptthread ausgeführt wird.
Die Intersection Observer API erfreut sich derzeit einer breiten Browserunterstützung, wie auf caniuse gezeigt wird.
Sie können mehr über die API in den Links im Ressourcenbereich lesen.
Sehen wir uns nun an, wie Sie diese API in einer echten React-App nutzen können. Die endgültige Version unserer App wird eine Seite mit Bildern sein, die endlos scrollt und bei der jedes Bild träge geladen wird.
API-Aufrufe mit dem useEffect
Hook durchführen
Klonen Sie zunächst das Startprojekt von dieser URL. Es hat eine minimale Einrichtung und einige definierte Stile. Ich habe auch einen Link zum CSS von Bootstrap
in der Datei public/index.html
hinzugefügt, da ich ihre Klassen für das Styling verwenden werde.
Fühlen Sie sich frei, ein neues Projekt zu erstellen, wenn Sie möchten. Stellen Sie sicher, dass Sie den yarn
-Manager installiert haben, wenn Sie dem Repo folgen möchten. Hier finden Sie die Installationsanleitung für Ihr spezifisches Betriebssystem.
Für dieses Tutorial werden wir Bilder von einer öffentlichen API abrufen und sie auf der Seite anzeigen. Wir werden die Lorem Picsum APIs verwenden.
Für dieses Tutorial verwenden wir den Endpunkt https://picsum.photos/v2/list?page=0&limit=10
, der ein Array von Bildobjekten zurückgibt. Um die nächsten zehn Bilder zu erhalten, ändern wir den Wert von Seite auf 1, dann auf 2 und so weiter.
Wir werden nun die App-Komponente Stück für Stück bauen.
Öffnen src/App.js
und geben Sie den folgenden Code ein.
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 }
Zuerst definieren wir eine Reducer-Funktion, imgReducer
. Dieser Reduzierer handhabt zwei Aktionen.
- Die Aktion
STACK_IMAGES
verkettet dasimages
. - Die Aktion
FETCHING_IMAGES
den Wert derfetching
zwischentrue
undfalse
um.
Der nächste Schritt besteht darin, diesen Reducer mit einem useReducer
Hook zu verbinden. Sobald dies erledigt ist, erhalten wir zwei Dinge zurück:
-
imgData
, das zwei Variablen enthält:images
ist das Array von Bildobjekten.fetching
ist ein boolescher Wert, der uns sagt, ob der API-Aufruf im Gange ist oder nicht. -
imgDispatch
, eine Funktion zum Aktualisieren des Reducer-Objekts.
Weitere Informationen zum useReducer
Hook finden Sie in der React-Dokumentation.
Im nächsten Teil des Codes führen wir den API-Aufruf durch. Fügen Sie den folgenden Code unter dem vorherigen Codeblock in App.js
.
// 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
Innerhalb des useEffect
rufen wir den API-Endpunkt mit fetch
API auf. Anschließend aktualisieren wir das Bilder-Array mit dem Ergebnis des API-Aufrufs, indem wir die Aktion STACK_IMAGES
. Wir senden auch die Aktion FETCHING_IMAGES
, sobald der API-Aufruf abgeschlossen ist.
Der nächste Codeblock definiert den Rückgabewert der Funktion. Geben Sie den folgenden Code nach dem useEffect
Hook ein.
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> );
Um die Bilder anzuzeigen, ordnen wir das images-Array im imgData
Objekt zu.
Starten Sie nun die App und sehen Sie sich die Seite im Browser an. Sie sollten die Bilder gut in einem responsiven Raster angezeigt sehen.
Der letzte Schritt besteht darin, die App-Komponente zu exportieren.
export default App;
Die entsprechende Verzweigung an dieser Stelle ist 01-make-api-calls.
Lassen Sie uns dies jetzt erweitern, indem wir beim Scrollen der Seite mehr Bilder anzeigen.
Implementierung von Infinite Scroll
Unser Ziel ist es, mehr Bilder zu präsentieren, wenn die Seite weiterscrollt. Aus der URL des API-Endpunkts, https://picsum.photos/v2/list?page=0&limit=10
, wissen wir, dass wir zum Abrufen einer neuen Reihe von Fotos nur den Wert von page
müssen. Wir müssen dies auch tun, wenn uns die Bilder zum Zeigen ausgehen. Für unseren Zweck hier wissen wir, dass uns die Bilder ausgegangen sind, wenn wir das Ende der Seite erreicht haben. Es ist an der Zeit zu sehen, wie uns die Intersection Observer API dabei hilft.
Öffnen src/App.js
und erstellen Sie einen neuen Reducer, pageReducer
, unterhalb 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 })
Wir definieren nur einen Aktionstyp. Jedes Mal, wenn die Aktion ADVANCE_PAGE
ausgelöst wird, wird der Wert von page
um 1 erhöht.
Aktualisieren Sie die URL in der fetch
, um Seitenzahlen wie unten gezeigt dynamisch zu akzeptieren.
fetch(`https://picsum.photos/v2/list?page=${pager.page}&limit=10`)
Fügen Sie pager.page
neben imgData
zum Abhängigkeitsarray hinzu. Dadurch wird sichergestellt, dass der API-Aufruf ausgeführt wird, wenn sich pager.page
ändert.
useEffect(() => { ... }, [ imgDispatch, pager.page ])
Geben Sie nach dem useEffect
Hook für den API-Aufruf den folgenden Code ein. Aktualisieren Sie auch Ihre Importzeile.
// 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]);
Wir definieren eine Variable bottomBoundaryRef
und setzen ihren Wert auf useRef(null)
. useRef
lässt Variablen ihre Werte über Komponenten-Renderings hinweg beibehalten, dh der aktuelle Wert der Variablen bleibt bestehen, wenn die enthaltende Komponente erneut rendert. Die einzige Möglichkeit, ihren Wert zu ändern, besteht darin, die Eigenschaft .current
dieser Variablen neu zuzuweisen.
In unserem Fall beginnt bottomBoundaryRef.current
mit einem Wert von null
. Während der Seitenrenderzyklus fortschreitet, setzen wir seine aktuelle Eigenschaft auf den Knoten <div id='page-bottom-boundary'>
.
Wir verwenden die Zuweisungsanweisung ref={bottomBoundaryRef}
, um React anzuweisen, bottomBoundaryRef.current
auf das div zu setzen, in dem diese Zuweisung deklariert wird.
Daher,
bottomBoundaryRef.current = null
wird am Ende des Rendering-Zyklus zu:
bottomBoundaryRef.current = <div></div>
Wir werden gleich sehen, wo diese Aufgabe erledigt wird.
Als Nächstes definieren wir eine scrollObserver
Funktion, in der der Beobachter festgelegt wird. Diese Funktion akzeptiert einen zu beobachtenden DOM
-Knoten. Der wichtigste Punkt, der hier zu beachten ist, ist, dass wir immer dann, wenn wir die beobachtete Kreuzung treffen, die ADVANCE_PAGE
Aktion auslösen. Der Effekt besteht darin, den Wert von pager.page
um 1 zu erhöhen. Sobald dies geschieht, wird der useEffect
Hook, der ihn als Abhängigkeit hat, erneut ausgeführt. Dieser erneute Lauf wiederum ruft den Abrufaufruf mit der neuen Seitennummer auf.
Der Ereigniszug sieht so aus.
Schnittpunkt unter Beobachtung treffen →ADVANCE_PAGE
Aktion aufrufen → Wert vonpager.page
um 1 erhöhen →useEffect
Hook für Fetch-Call-Läufe →fetch
-Call wird ausgeführt → Zurückgegebene Bilder werden mit demimages
-Array verkettet.
Wir rufen scrollObserver
in einem useEffect
Hook auf, sodass die Funktion nur ausgeführt wird, wenn sich eine der Abhängigkeiten des Hooks ändert. Wenn wir die Funktion nicht innerhalb eines useEffect
-Hooks aufrufen würden, würde die Funktion auf jeder gerenderten Seite ausgeführt.
Denken Sie daran, dass bottomBoundaryRef.current
auf <div id="page-bottom-boundary" style="border: 1px solid red;"></div>
. Wir überprüfen, ob sein Wert nicht null ist, bevor wir ihn an scrollObserver
. Andernfalls würde der IntersectionObserver
-Konstruktor einen Fehler zurückgeben.
Da wir scrollObserver
in einem useEffect
Hook verwendet haben, müssen wir ihn in einen useCallback
-Hook einschließen, um zu verhindern, dass Komponenten erneut gerendert werden. Weitere Informationen zu useCallback finden Sie in der React-Dokumentation.
Geben Sie den folgenden Code nach dem <div id='images'>
div ein.
// 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>
Wenn der API-Aufruf startet, setzen wir fetching
auf true
und der Text Getting images wird sichtbar. Sobald es fertig ist, setzen wir fetching
auf false
und der Text wird ausgeblendet. Wir könnten den API-Aufruf auch auslösen, bevor wir genau die Grenze erreicht haben, indem wir einen anderen threshold
im Konstruktoroptionsobjekt festlegen. Die rote Linie am Ende lässt uns genau sehen, wann wir die Seitengrenze erreicht haben.
Die entsprechende Verzweigung an dieser Stelle ist 02-unendliche Schriftrolle.
Wir werden jetzt das verzögerte Laden von Bildern implementieren.
Implementierung von Image Lazy Loading
Wenn Sie beim Herunterscrollen die Netzwerkregisterkarte überprüfen, werden Sie sehen, dass der API-Aufruf erfolgt, sobald Sie die rote Linie (die untere Grenze) erreichen, und alle Bilder geladen werden, auch wenn Sie noch nicht zum Anzeigen gekommen sind Ihnen. Es gibt eine Vielzahl von Gründen, warum dies möglicherweise kein wünschenswertes Verhalten ist. Möglicherweise möchten wir Netzwerkaufrufe speichern, bis der Benutzer ein Bild sehen möchte. In einem solchen Fall könnten wir uns dafür entscheiden, die Bilder träge zu laden, dh wir werden ein Bild erst laden, wenn es in die Ansicht gescrollt wird.
Öffnen src/App.js
. Geben Sie direkt unter den unendlichen Bildlauffunktionen den folgenden Code ein.
// 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]);
Wie bei scrollObserver
definieren wir eine Funktion, imgObserver
, die einen zu beobachtenden Knoten akzeptiert. Wenn die Seite auf eine Kreuzung trifft, wie durch en.intersectionRatio > 0
bestimmt, tauschen wir die Bildquelle auf dem Element aus. Beachten Sie, dass wir zuerst prüfen, ob die neue Bildquelle vorhanden ist, bevor wir den Austausch durchführen. Wie bei der scrollObserver
Funktion packen wir imgObserver in einen useCallback
-Hook, um ein endloses erneutes Rendern der Komponente zu verhindern.
Beachten Sie auch, dass wir aufhören, ein img
-Element zu beobachten, sobald wir mit der Substitution fertig sind. Wir tun dies mit der unobserve
Methode.
Im folgenden useEffect
Hook erfassen wir alle Bilder mit der Klasse .card-img-top
auf der Seite mit document.querySelectorAll
. Dann iterieren wir über jedes Bild und setzen einen Beobachter darauf.
Beachten Sie, dass wir imgData.images
als Abhängigkeit des useEffect
Hooks hinzugefügt haben. Wenn sich dies ändert, löst es den useEffect
Hook aus und imgObserver
wird wiederum mit jedem <img className='card-img-top'>
Element aufgerufen.
Aktualisieren Sie das Element <img className='card-img-top'/>
wie unten gezeigt.
<img alt={author} data-src={download_url} className="card-img-top" src={'https://picsum.photos/id/870/300/300?grayscale&blur=2'} />
Wir legen eine Standardquelle für jedes <img className='card-img-top'/>
Element fest und speichern das Bild, das wir anzeigen möchten, in der data-src
Eigenschaft. Das Standardbild hat normalerweise eine kleine Größe, damit wir so wenig wie möglich herunterladen. Wenn das Element <img/>
angezeigt wird, ersetzt der Wert der Eigenschaft data-src
das Standardbild.
Im Bild unten sehen wir das standardmäßige Leuchtturmbild, das immer noch in einigen Räumen zu sehen ist.
Der entsprechende Zweig an dieser Stelle ist 03-Lazy-Loading.
Sehen wir uns nun an, wie wir all diese Funktionen abstrahieren können, damit sie wiederverwendbar sind.
Abstrahierendes Abrufen, unendliches Scrollen und faules Laden in benutzerdefinierte Hooks
Wir haben Fetch, Infinite Scroll und Image Lazy Loading erfolgreich implementiert. Wir haben möglicherweise eine andere Komponente in unserer Anwendung, die eine ähnliche Funktionalität benötigt. In diesem Fall könnten wir diese Funktionen abstrahieren und wiederverwenden. Wir müssen sie nur in eine separate Datei verschieben und dort importieren, wo wir sie brauchen. Wir wollen sie in Custom Hooks verwandeln.
Die React-Dokumentation definiert einen benutzerdefinierten Hook als eine JavaScript-Funktion, deren Name mit "use"
beginnt und die andere Hooks aufrufen kann. In unserem Fall möchten wir drei Hooks erstellen, useFetch
, useInfiniteScroll
, useLazyLoading
.
Erstellen Sie eine Datei im Ordner src/
. Nennen Sie es customHooks.js
und fügen Sie den folgenden Code ein.
// 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
Der Hook useFetch
akzeptiert eine Dispatch-Funktion und ein Datenobjekt. Die Dispatch-Funktion übergibt die Daten vom API-Aufruf an die App
-Komponente, während das Datenobjekt uns die Aktualisierung der API-Endpunkt-URL ermöglicht.
// 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
Der Hook useInfiniteScroll
akzeptiert eine scrollRef
und eine dispatch
-Funktion. Die scrollRef
hilft uns beim Einrichten des Beobachters, wie bereits in dem Abschnitt besprochen, in dem wir sie implementiert haben. Die Dispatch-Funktion bietet die Möglichkeit, eine Aktion auszulösen, die die Seitenzahl in der API-Endpunkt-URL aktualisiert.
// 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]) }
Der Hook useLazyLoading
erhält einen Selektor und ein Array. Der Selektor wird verwendet, um die Bilder zu finden. Jede Änderung im Array löst den useEffect
Hook aus, der den Beobachter für jedes Bild einrichtet.
Wir können sehen, dass es die gleichen Funktionen sind, die wir in src/App.js
haben, die wir in eine neue Datei extrahiert haben. Das Gute ist jetzt, dass wir Argumente dynamisch übergeben können. Lassen Sie uns nun diese benutzerdefinierten Hooks in der App-Komponente verwenden.
Öffnen src/App.js
. Importieren Sie die benutzerdefinierten Hooks und löschen Sie die Funktionen, die wir für das Abrufen von Daten, das unendliche Scrollen und das verzögerte Laden von Bildern definiert haben. Verlassen Sie die Reducer und die Abschnitte, in denen wir useReducer
verwenden. Fügen Sie den folgenden Code ein.
// 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 ( ... )
Über bottomBoundaryRef
haben wir bereits im Abschnitt über unendliches Scrollen gesprochen. Wir übergeben das pager
-Objekt und die Funktion imgDispatch
an useFetch
. useLazyLoading
akzeptiert den Klassennamen .card-img-top
. Beachten Sie die .
im Klassennamen enthalten. Auf diese Weise müssen wir document.querySelectorAll
nicht angeben. useInfiniteScroll
akzeptiert sowohl eine Referenz als auch die Dispatch-Funktion zum Erhöhen des Werts von page
.
Der entsprechende Zweig an dieser Stelle ist 04-Custom-Hooks.
Fazit
HTML wird immer besser darin, nette APIs für die Implementierung cooler Funktionen bereitzustellen. In diesem Beitrag haben wir gesehen, wie einfach es ist, den Schnittmengenbeobachter in einer React-Funktionskomponente zu verwenden. Dabei haben wir gelernt, wie man einige Hooks von React verwendet und wie man eigene Hooks schreibt.
Ressourcen
- „Infinite Scroll + Lazy Loading“, Orji Chidi Matthew, GitHub
- „Unendliches Scrollen, Seitenumbruch oder „Mehr laden“-Buttons? Usability-Ergebnisse im E-Commerce“, Christian Holst, Smashing Magazine
- „Lorem Picsum“, David Marby & Nijiko Yonskai
- „IntersectionObserver kommt in Sicht“, Surma, Web Fundamentals
- Kann ich …
IntersectionObserver
verwenden - „Intersection Observer API“, MDN-Webdokumentation
- „Komponenten und Requisiten“, Reagieren
- „
useCallback
“, Reagieren - „
useReducer
“, Reagieren