Maison  >  Article  >  interface Web  >  Construire un composant de défilement infini dans React

Construire un composant de défilement infini dans React

WBOY
WBOYoriginal
2024-08-26 21:45:021101parcourir

Introduction

Nous voyons un défilement infini dans les applications et les pages Web, en particulier dans les médias sociaux, qui veulent simplement que nous fassions défiler. Bien que faire défiler sans réfléchir ne soit pas une bonne chose, créer votre propre défilement infini est génial. En tant que développeur, nous devrions essayer de recréer les composants que nous voyons en surfant sur le Web. Cela peut vous mettre au défi d'en savoir plus et de sortir des sentiers battus lors de la mise en œuvre de certains composants.

De plus, si vous souhaitez implémenter un défilement infini dans votre application, vous pouvez suivre le guide pour créer le vôtre. Vous pouvez ajouter votre propre code pour améliorer le comportement du défilement.

Dans cet article, nous allons créer un composant de défilement infini à partir de zéro. Il couvrira les sujets suivants :

  • Configuration de l'environnement
  • Construire le composant
  • Ajout de CSS
  • Optimisation du parchemin infini

Maintenant, commençons.

Configuration de l'environnement

Nous allons utiliser CRA pour créer l'application React de base. Vous pouvez le faire en exécutant la commande suivante :

    npx create-react-app infinite-scroll

Si vous souhaitez Vite ou NextJS, vous pouvez également le faire. Hormis des changements mineurs, les autres choses resteront les mêmes.

Remarque : Pour exécuter cette commande, vous devez avoir NodeJS préinstallé. Supprimez également certains codes passe-partout inutiles de l’ARC.

Nous allons avoir besoin d'une dépendance pour récupérer les données d'une API. Après avoir paramétré React, nous pouvons installer Axios avec la commande suivante :

    npm install axios

Maintenant, nous sommes prêts à créer le composant.

Composant d'application

Nous allons créer un composant qui va récupérer les données de films populaires à partir de l'API Tmdb. C'est gratuit, vous pouvez obtenir leur clé API sur leur site Web. Construisons d'abord l'endroit où ils récupèrent les données, puis ajoutons des fonctionnalités de défilement infinies.

Voici le code du composant App :

App.js

    import "./App.css";
    import { useState, useEffect } from "react";
    import axios from "axios";
    import { MovieCard } from "./MovieCard";

    function App() {
      const [page, setPage] = useState(1); // for number of page in tmdb 
      const [data, setData] = useState([]); // storing the fetched data
      const [loading, setLoading] = useState(false); // for setting loading state

      // fetching and stroring the data in the state
      const fetchMovie = async () => {
        const URL = `https://api.themoviedb.org/3/movie/popular?language=en-US&page=${page}`;
        const data = await axios.get(URL, {
          headers: {
            Authorization:
              "Bearer API KEY",
            Accept: "application/json",
          },
        });
        setData((prevData) => [...prevData, ...data.data.results]); // we are going to add the new data to current data.
        setLoading(false);
      };

      // useEffecte for invoking the function at the start
      useEffect(() => {
        fetchMovie();
      }, [page]);

      return (
        <div className="App">
          <header className="App-header">
            Popular movies according to Tmdb
            <div className="movieCardContainer">
              {data.length > 1 &&
                data.map((item) => {
                  return (
                    <MovieCard
                      key={item.id}
                      title={item.original_title}
                      description={item.overview}
                      rating={item.vote_average}
                      imageURL={item.poster_path}
                    />
                  );
                })}
              {loading && <h1>Loading....</h1>}
            </div>
          </header>
        </div>
      );
    }

    export default App;

Vous pouvez à peu près comprendre le code, où nous récupérons les données et les transmettons au composant MovieCard en tant qu'accessoire.

Créez un composant MovieCard.js pour afficher les informations de chaque film.

MoveCard.js

    import React from "react";

    export const MovieCard = ({ title, description, imageURL, rating }) => {

      const imagePath = `https://image.tmdb.org/t/p/w500${imageURL}`; // poster image path URL 

      return (
        <div className="movieCard">
          <img src={imagePath} height={400} />
          <div className="movieInfo">
            <h3>{title}</h3>
            <p>{description}</p>
            <p>{rating.toFixed(1)}⭐</p>
          </div>
        </div>
      );
    };

Voici le CSS de l'application :

App.css

    .App {
      text-align: center;
    }

    .App-header {
      background-color: #282c34;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding-top: 1em;
      font-size: calc(10px + 2vmin);
      color: white;
    }

    .movieCardContainer{
      margin-top: 1em;
      display: flex;
      flex-direction: column;
      gap: 1em;
      width: 60%;
      max-width: 800px;
    }

    .movieCard{
      display: flex;
    }

    .movieInfo{
      margin-left: 1em;
      text-align: left;
    }

    p{
      font-size: 18px;
    }

Parchemin infini

Maintenant, commençons par comprendre comment nous allons construire le parchemin infini. Pour cela, nous allons regarder la position de la barre de défilement. Lorsque la position de la barre de défilement est juste au-dessus de la fin de la page, nous allons définir l'état de chargement sur true.

Nous allons avoir un autre useEffect qui va incrémenter l'état de la page de 1. Une fois le numéro de page mis à jour, le useEffect initial qui a la page comme dépendance se déclenchera. Cela invoquera la fonction fetchMovie() pour récupérer les données.

Ajout d'EventListner au défilement

Tout d'abord, nous allons ajouter même l'écoute pour savoir quand la position de la barre de défilement est modifiée.

    window.addEventListener("scroll", handleScroll);

handleScroll

Lorsque le défilement se produit, nous allons vérifier si la position actuelle de la barre de défilement est juste au-dessus du bas de la page Web (c'est-à-dire la zone de défilement verticale totale). Si oui, nous changeons l'état de chargement en vrai.

    const handleScroll = () => {
      if (document.body.scrollHeight - 300 < window.scrollY + window.innerHeight) {
        setLoading(true);
      }
    };
  • scrollHeight : C'est la propriété qui renvoie la hauteur totale du contenu, y compris la partie qui n'est pas visible à l'écran. Ce sera donc la zone de défilement totale.
  • scrollY : C'est la propriété qui renvoie le nombre de pixels sur lesquels le document a défilé verticalement à partir du haut. Ce sera donc la zone qui a défilé.
  • innerHeight : C'est la propriété qui renvoie la hauteur de la zone de contenu Windows du navigateur. Ce sera la largeur de la barre de défilement. Il est ajouté à scrollY afin que la récupération se produise lorsque nous atteignons le contenu plutôt que lorsque nous transmettons le contenu. ## useEffect

Après avoir réussi à changer l'état de chargement, nous pouvons implémenter un useEffect pour incrémenter le numéro de page. Ainsi, la récupération des données du film peut avoir lieu.

    useEffect(() => {
      if (loading == true) {
        setPage((prevPage) => prevPage + 1);
      }
    }, [loading]);

    // other useEffect that we already implemented

    useEffect(() => {
      fetchMovie();
    }, [page]);

Optimisation du eventListner

Étant donné que le défilement peut déclencher handleScroll plusieurs fois pendant le défilement, cela entraînera un appel inutile de la fonction plusieurs fois. Nous pouvons ajouter un anti-rebond à la fonction afin que cela puisse prendre un certain temps avant d'invoquer la fonction.

    // debounce function
    function debounce(func, delay) {
      let timeoutId;
      return function (...args) {
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(() => {
          func(...args);
        }, delay);
      };
    }

    // adding debounce to the eventListner
    window.addEventListener("scroll", debounce(handleScroll, 500));

Voici le code complet de l'App.js :

    import "./App.css";
    import { useState, useEffect } from "react";
    import axios from "axios";
    import { MovieCard } from "./MovieCard";

    function App() {
      const [page, setPage] = useState(1);
      const [data, setData] = useState([]);
      const [loading, setLoading] = useState(false);
      const fetchMovie = async () => {

        const URL = `https://api.themoviedb.org/3/movie/popular?language=en-US&page=${page}`;
        const data = await axios.get(URL, {
          headers: {
            Authorization:
              "Bearer API KEY",
            Accept: "application/json",
          },
        });
        setData((prevData) => [...prevData, ...data.data.results]);
        setLoading(false);
      };
      useEffect(() => {
        fetchMovie();
      }, [page]);

      const handleScroll = () => {
        if (
          document.body.scrollHeight - 300 <
          window.scrollY + window.innerHeight
        ) {
          setLoading(true);
        }
      };

      function debounce(func, delay) {
        let timeoutId;
        return function (...args) {
          if (timeoutId) {
            clearTimeout(timeoutId);
          }
          timeoutId = setTimeout(() => {
            func(...args);
          }, delay);
        };
      }

      window.addEventListener("scroll", debounce(handleScroll, 500));

      useEffect(() => {
        if (loading == true) {
          setPage((prevPage) => prevPage + 1);
        }
      }, [loading]);

      return (
        <div className="App">
          <header className="App-header">
            Popular movies according to Tmdb
            <div className="movieCardContainer">
              {data.length > 1 &&
                data.map((item) => {
                  return (
                    <MovieCard
                      key={item.id}
                      title={item.original_title}
                      description={item.overview}
                      rating={item.vote_average}
                      imageURL={item.poster_path}
                    />
                  );
                })}
              {loading && <h1>Loading....</h1>}
            </div>
          </header>
        </div>
      );
    }

    export default App;

Voici le GIF démontrant le fonctionnement de l'application.

Building an Infinite Scroll Component in React

Conclusion

Construire un composant de défilement infini dans React peut être une expérience très enrichissante. Il améliore non seulement votre compréhension du fonctionnement du défilement, mais vous apprend également la gestion de l'état, les écouteurs d'événements et les techniques d'optimisation telles que l'anti-rebond. En suivant ce guide, vous disposez désormais d'une configuration de base de défilement infini que vous pouvez personnaliser et améliorer en fonction de vos besoins.

Que vous affichiez des données de films, des articles de blog ou tout autre contenu, ce composant constitue une base solide. N'oubliez pas que la clé est de garantir une expérience utilisateur fluide en gérant soigneusement quand et comment les données sont récupérées lorsque l'utilisateur fait défiler. Bon codage !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn