Dans cet article, nous explorerons comment créer une page de flux à l'aide de React Query !
Voici ce que nous allons créer :
Cet article ne couvrira pas toutes les étapes et tous les détails impliqués dans la création de l'application.
Au lieu de cela, nous nous concentrerons sur les fonctionnalités clés, en particulier les fonctionnalités de « défilement infini » et de « défilement vers le haut ».
Si vous souhaitez consulter l'intégralité de l'implémentation, vous pouvez trouver la base de code complète dans ce référentiel GitHub.
Tout d'abord, nous allons créer notre application React en utilisant Vite avec la commande suivante :
npm create vite@latest feed-page-rq -- --template react-ts
Et nous installerons les dépendances requises, axios et react-query :
npm install axios @tanstack/react-query@4
Nous devons également simuler un serveur RESTful, nous utiliserons donc json-server, qui nous permet de simuler un backend en fournissant de faux points de terminaison d'API pour notre application React.
Nous travaillerons avec une entité de publication qui comprend les attributs suivants :
{ "id": "1", "title": "Sample Post Title", "body": "This is a sample post body", "userId": "2", "createdAt": 1728334799169 // date timestamp }
Une fois le serveur configuré, nous l'exécuterons en utilisant :
npx json-server --watch db.json
Le mécanisme de la fonctionnalité « Infinite Scroll » est simple :
Lorsque l'utilisateur fait défiler la liste des publications et s'approche du bas du conteneur, React Query recherchera le prochain lot de publications. Ce processus se répète jusqu'à ce qu'il n'y ait plus de messages à charger.
Nous vérifions si l'utilisateur se trouve près du bas en ajoutant la position de défilement actuelle (scrollTop) à la hauteur de l'écran visible (clientHeight) et en comparant cette somme avec la hauteur totale du conteneur (scrollHeight).
Si la somme est supérieure ou égale à la hauteur totale du conteneur, nous demandons à React Query de récupérer la page suivante.
const { scrollTop, scrollHeight, clientHeight } = elemRef.current; if(scrollTop clientHeight >= scrollHeight) { fetchNextPage(); }
Tout d'abord, nous allons créer un hook personnalisé pour envelopper useInfiniteQuery de React Query.
Dans le hook personnalisé, nous configurons la requête pour récupérer les publications page par page, en spécifiant le numéro de page initial et la fonction qui récupère les pages suivantes :
import { QueryFunctionContext, useInfiniteQuery } from "@tanstack/react-query"; import axios from "axios"; const URL = "http://localhost:3000"; const POSTS = "posts"; export const fetchInfinitePosts = async ({ pageParam, }: QueryFunctionContext) => { const result = await axios.get( `${URL}/${POSTS}?_sort=-createdAt&_page=${pageParam}&_per_page=10`, ); return result.data; }; export const useInfinitePosts = () => { return useInfiniteQuery({ queryKey: [POSTS], queryFn: fetchInfinitePosts, initialPageParam: 1, getNextPageParam: (lastPage) => lastPage.next, }); };
Maintenant, nous allons utiliser le hook personnalisé dans notre composant pour afficher la liste des publications.
Pour ce faire, nous parcourons d'abord les pages, puis parcourons les publications de chaque page pour les afficher.
import { useInfinitePosts } from './hooks/useInfinitePosts'; const PostList = () => { const { data: postLists } = useInfinitePosts(); return ({postLists?.pages.map((page) => page.data.map(post => (); }; export default PostList;)) )}{post.title}
{post.body}
Pour implémenter le comportement de défilement infini, nous devons ajouter un écouteur d'événement de défilement au conteneur où les publications sont affichées. Cet écouteur d'événements déclenche la fonction onScroll, qui vérifie si l'utilisateur se trouve près du bas du conteneur et, si c'est le cas, appelle fetchNextPage pour charger plus de contenu.
import React, { useRef, useEffect } from 'react'; import { useInfinitePosts } from './hooks/useInfinitePosts'; const PostList = () => { const { data: postLists, fetchNextPage } = useInfinitePosts(); const elemRef = useRef(null); const onScroll = useCallback(() => { if (elemRef.current) { const { scrollTop, scrollHeight, clientHeight } = elemRef.current; const isNearBottom = scrollTop clientHeight >= scrollHeight; if(isNearBottom) { fetchNextPage(); } } }, [fetchNextPage]); useEffect(() => { const innerElement = elemRef.current; if (innerElement) { innerElement.addEventListener("scroll", onScroll); return () => { innerElement.removeEventListener("scroll", onScroll); }; } }, [onScroll]); return ({postLists?.pages.map((page, i) => page.data.map(post => (); }; export default PostList;)) )}{post.title}
{post.body}
Ensuite, nous allons créer un bouton « Faire défiler vers le haut » qui apparaît lorsqu'un nouveau message est ajouté. Ce bouton permet à l'utilisateur de revenir rapidement en haut pour voir la dernière mise à jour.
Étant donné que les publications sont triées par date de création, toute publication nouvellement ajoutée apparaîtra en haut de la liste.
La logique de notre fonctionnalité sera construite sur cette prémisse.
Nous commençons par créer une nouvelle requête pour récupérer et mettre en cache la dernière publication créée. Nous appellerons cet article prevNewestPost.
Nous voulons que prevNewestPost reste quelques pas en retard, ou tout au plus, corresponde au premier message de la liste. Nous allons donc contrôler manuellement sa récupération.
Nous y parviendrons en définissant activé : false dans les options de requête.
export const fetchNewestPost = async () => { const result = await axios.get(`${URL}/${POSTS}?_sort=-createdAt`); return result.data[0]; }; export const useNewestPost = () => { return useQuery({ queryKey: [POSTS, "newest"], queryFn: () => fetchNewestPost(), enabled: false, }); };
Avec React Query, la liste des publications est mise à jour automatiquement sur des événements spécifiques. (Voici le lien de documentation pour une liste complète de ces événements.)
Nous utiliserons cette liste mise à jour pour déterminer quand afficher le bouton « Faire défiler vers le haut » en comparant prevNewestPost avec le premier message.
S'ils sont différents, cela indique qu'un nouveau message a été ajouté, donc le bouton « Faire défiler vers le haut » sera affiché.
setIsShowButton(postLists?.pages[0].data[0].id !== prevNewestPost?.id);
Nous ne devrions pas afficher le bouton « Faire défiler vers le haut » lorsque l'utilisateur se trouve en haut du conteneur de liste de publications.
Ainsi, lorsque l'utilisateur atteint le sommet, nous devons resynchroniser le prevNewestPost avec le dernier message actuel en déclenchant une récupération de requête.
const { data: prevNewestPost, refetch } = useNewestPost(); const [isShowButton, setIsShowButton] = useState(false); useEffect(() => { if (!isNearTop) { setIsShowButton(postLists?.pages[0].data[0].id !== prevNewestPost?.id); } else { setIsShowButton(false); refetch(); } }, [postLists, prevNewestPost, isNearTop]);
Cliquer sur le bouton ToTopBtn fera défiler vers le haut de la liste, déclenchant la logique existante pour masquer le bouton et récupérer les données pour synchroniser prevNewestPost avec le premier message de la liste.
import { RefObject } from "react"; type ToTopBtnProps = { elemRef: RefObject; }; export default function ToTopBtn({ elemRef }: ToTopBtnProps) { return ( ); }
Pour tester la fonctionnalité du bouton « Faire défiler vers le haut », nous devons ajouter de nouvelles publications au flux.
Pour cela, nous utiliserons useMutation de React Query pour ajouter une nouvelle publication au serveur et revalider notre postList en cache après chaque mutation.
Nous allons mettre en place une mutation qui nous permettra de créer une nouvelle publication avec des données aléatoires à chaque fois que l'utilisateur clique sur un bouton.
export const savePost = async (post: NewPostData) => axios.post(`${URL}/${POSTS}`, post); export const useAddPost = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: savePost, onSuccess: () => { queryClient.invalidateQueries({ queryKey: [POSTS] }); }, }); };
export default function AddNewPostBtn() { const mutation = useAddPost(); return ();
Dans ce didacticiel, nous avons exploré la puissance de React Query à travers un cas d'utilisation réel, soulignant sa capacité à aider les développeurs à créer des interfaces dynamiques qui améliorent l'expérience utilisateur.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3