frontend: Pagination au scroll

This commit is contained in:
Divlo 2020-03-21 18:24:10 +01:00
parent 895d0c7f6b
commit ea13959c91
2 changed files with 28 additions and 23 deletions

View File

@ -1,9 +1,9 @@
import Link from 'next/link'; import Link from 'next/link';
import { useState, Fragment } from 'react'; import { useState, Fragment, forwardRef } from 'react';
import Loader from '../Loader/Loader'; import Loader from '../Loader/Loader';
import './FunctionCard.css'; import './FunctionCard.css';
const FunctionCard = (props) => { const FunctionCard = forwardRef((props, ref) => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
@ -14,8 +14,9 @@ const FunctionCard = (props) => {
return ( return (
<Link href={`/functions/${props.slug}`}> <Link href={`/functions/${props.slug}`}>
<Fragment> <Fragment>
<div className={"FunctionCard col-sm-24 col-md-10 col-xl-7"}> {/* Elément à une hauteur pendant chargement */}
{isLoading && <Loader width="100px" height="100px" />} <div ref={ref} style={isLoading ? { height: "200px", justifyContent: "center" } : null} className={"FunctionCard col-sm-24 col-md-10 col-xl-7"}>
{isLoading && <Loader width="125px" height="125px" />}
<div className={`FunctionCard__container ${isLoading ? "d-none" : ""}`}> <div className={`FunctionCard__container ${isLoading ? "d-none" : ""}`}>
<div className="FunctionCard__top"> <div className="FunctionCard__top">
<img onLoad={handleLoad} className="FunctionCard__image" alt={props.title} src={props.image} /> <img onLoad={handleLoad} className="FunctionCard__image" alt={props.title} src={props.image} />
@ -31,6 +32,6 @@ const FunctionCard = (props) => {
</Fragment> </Fragment>
</Link> </Link>
); );
} })
export default FunctionCard; export default FunctionCard;

View File

@ -1,4 +1,4 @@
import { Fragment, useState, useEffect } from 'react'; import { Fragment, useState, useEffect, useRef, useCallback } from 'react';
import HeadTag from '../components/HeadTag'; import HeadTag from '../components/HeadTag';
import FunctionCard from '../components/FunctionCard/FunctionCard'; import FunctionCard from '../components/FunctionCard/FunctionCard';
import Loader from '../components/Loader/Loader'; import Loader from '../components/Loader/Loader';
@ -18,6 +18,19 @@ const Functions = () => {
const [isLoadingFunctions, setLoadingFunctions] = useState(true); const [isLoadingFunctions, setLoadingFunctions] = useState(true);
const [pageFunctions, setPageFunctions] = useState(1); const [pageFunctions, setPageFunctions] = useState(1);
// Permet la pagination au scroll
const observer = useRef();
const lastFunctionCardRef = useCallback((node) => {
if (isLoadingFunctions) return;
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && functionsData.hasMore) {
setPageFunctions(pageFunctions + 1);
}
}, { threshold: 1 });
if (node) observer.current.observe(node);
}, [isLoadingFunctions, functionsData.hasMore]);
const getFunctionsData = () => { const getFunctionsData = () => {
setLoadingFunctions(true); setLoadingFunctions(true);
return new Promise(async (next) => { return new Promise(async (next) => {
@ -40,10 +53,6 @@ const Functions = () => {
getFunctionsData().then((data) => setFunctionsData(data)); getFunctionsData().then((data) => setFunctionsData(data));
}, [inputSearch.selectedCategory, inputSearch.search]); }, [inputSearch.selectedCategory, inputSearch.search]);
const loadMore = () => {
setPageFunctions(pageFunctions + 1);
}
const handleChange = (event) => { const handleChange = (event) => {
const inputSearchNew = { ...inputSearch }; const inputSearchNew = { ...inputSearch };
inputSearchNew[event.target.name] = event.target.value; inputSearchNew[event.target.name] = event.target.value;
@ -74,20 +83,15 @@ const Functions = () => {
</div> </div>
<div className="row justify-content-center"> <div className="row justify-content-center">
{functionsData.rows.map((f) => ( {functionsData.rows.map((f, index) => {
<FunctionCard key={f.id} slug={f.slug} image={API_URL + f.image} title={f.title} description={f.description} category={f.categorie} publicationDate={new Date(f.createdAt).toLocaleDateString('fr-FR')} /> // Si c'est le dernier élément
))} if (functionsData.rows.length === index + 1) {
</div> return <FunctionCard ref={lastFunctionCardRef} key={f.id} slug={f.slug} image={API_URL + f.image} title={f.title} description={f.description} category={f.categorie} publicationDate={new Date(f.createdAt).toLocaleDateString('fr-FR')} />;
{
isLoadingFunctions ?
<Loader width="100px" height="100px" />
: functionsData.hasMore ?
<div className="row justify-content-center">
<button className="btn btn-dark" style={{marginBottom: "50px"}} onClick={loadMore}>Charger plus de fonctions ?</button>
</div>
:
null
} }
return <FunctionCard key={f.id} slug={f.slug} image={API_URL + f.image} title={f.title} description={f.description} category={f.categorie} publicationDate={new Date(f.createdAt).toLocaleDateString('fr-FR')} />;
})}
</div>
{isLoadingFunctions && <Loader width="100px" height="100px" />}
</div> </div>
</Fragment> </Fragment>
); );