"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Construindo uma página de feed usando React Query

Construindo uma página de feed usando React Query

Publicado em 2024-11-09
Navegar:291

Building a Feed Page Using React Query

O objetivo

Neste artigo, exploraremos como construir uma página de feed usando React Query!

Aqui está o que criaremos:

Este artigo não cobrirá todas as etapas e detalhes envolvidos na construção do aplicativo.
Em vez disso, nos concentraremos nos principais recursos, especificamente nas funcionalidades de “rolagem infinita” e “rolagem para cima”.
Se você estiver interessado em consultar toda a implementação, você pode encontrar a base de código completa neste repositório GitHub.

Configurando o aplicativo

Primeiro, criaremos nossa aplicação React usando Vite com o seguinte comando:

npm create vite@latest feed-page-rq -- --template react-ts

E instalaremos as dependências necessárias, axios e react-query:

npm install axios @tanstack/react-query@4

Também precisamos simular um servidor RESTful, então usaremos json-server, que nos permite simular um back-end fornecendo endpoints de API falsos para nosso aplicativo React.

Trabalharemos com uma entidade de postagem que inclui os seguintes atributos:

{
  "id": "1",
  "title": "Sample Post Title",
  "body": "This is a sample post body",
  "userId": "2",
  "createdAt": 1728334799169 // date timestamp
}

Depois que o servidor estiver configurado, iremos executá-lo usando:

npx json-server --watch db.json

Implementando "Rolagem Infinita"

O mecanismo do recurso "Rolagem Infinita" é direto:
Quando o usuário percorre a lista de postagens e se aproxima da parte inferior do contêiner, o React Query procurará o próximo lote de postagens. Este processo se repete até que não haja mais postagens para carregar.

Verificamos se o usuário está próximo ao final adicionando a posição atual de rolagem (scrollTop) à altura visível da tela (clientHeight) e comparando essa soma com o altura total do contêiner (scrollHeight).
Se a soma for maior ou igual à altura total do contêiner, pedimos ao React Query para buscar a próxima página.

  const { scrollTop, scrollHeight, clientHeight } = elemRef.current;
  if(scrollTop   clientHeight >= scrollHeight) {
      fetchNextPage();
  }

Etapa 1: configurar useInfiniteQuery

Primeiro, criaremos um gancho personalizado para envolver useInfiniteQuery do React Query.

Dentro do hook customizado, configuramos a consulta para buscar posts página por página, especificando o número da página inicial e a função que recupera as próximas páginas:

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,
  });
};

Etapa 2: exibir postagens no PostList

Agora, usaremos o gancho personalizado em nosso componente para exibir a lista de postagens.
Para fazer isso, primeiro percorremos as páginas e, em seguida, iteramos as postagens em cada página para renderizá-las.

import { useInfinitePosts } from './hooks/useInfinitePosts';

const PostList = () => {
  const { data: postLists } = useInfinitePosts();

  return (
    
{postLists?.pages.map((page) => page.data.map(post => (

{post.title}

{post.body}

)) )}
); }; export default PostList;

Etapa 3: implementar o comportamento de rolagem infinita

Para implementar o comportamento de rolagem infinita, precisamos adicionar um ouvinte de evento de rolagem ao contêiner onde as postagens são exibidas. Este ouvinte de evento aciona a função onScroll, que verifica se o usuário está próximo ao final do contêiner e, em caso afirmativo, chama fetchNextPage para carregar mais conteúdo.

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 => (

{post.title}

{post.body}

)) )}
); }; export default PostList;

Implementando "Rolar para o topo"

A seguir, criaremos um botão "Rolar para o topo" que aparece quando uma nova postagem é adicionada. Este botão permite que o usuário retorne rapidamente ao topo para ver a atualização mais recente.
Como as postagens são classificadas por data de criação, qualquer postagem recém-adicionada aparecerá no topo da lista.
A lógica do nosso recurso será construída sobre essa premissa.

Etapa 1: crie uma consulta para prevNewestPost

Começamos criando uma nova consulta para buscar e armazenar em cache a última postagem criada. Chamaremos esta postagem de prevNewestPost.
Queremos que prevNewestPost fique alguns passos atrás ou, no máximo, corresponda ao primeiro post da lista. Portanto, controlaremos manualmente sua nova busca.
Conseguiremos isso definindo enabled: false nas opções de consulta.

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,
  });
};

Etapa 2: compare prevNewestPost com a primeira postagem

Com React Query, a lista de postagens é atualizada automaticamente em eventos específicos. (Aqui está o link da documentação para uma lista completa desses eventos.)
Usaremos esta lista atualizada para determinar quando exibir o botão 'Rolar para o topo' comparando prevNewestPost com a primeira postagem.
Se forem diferentes, isso indica que uma nova postagem foi adicionada, então o botão 'Rolar para o topo' será mostrado.

setIsShowButton(postLists?.pages[0].data[0].id !== prevNewestPost?.id);

Etapa 3: ocultar o botão quando o cursor estiver na parte superior

Não devemos mostrar o botão "Rolar para o topo" quando o usuário estiver no topo do contêiner da lista de postagens.
Portanto, quando o usuário chega ao topo, precisamos sincronizar novamente o prevNewestPost com a última postagem atual, acionando uma nova busca de consulta.

  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]);

Etapa 4: crie o botão Rolar para o topo

Clicar no botão ToTopBtn rolará para o topo da lista, acionando a lógica existente para ocultar o botão e buscar novamente os dados para sincronizar prevNewestPost com a primeira postagem da lista.

import { RefObject } from "react";

type ToTopBtnProps = {
  elemRef: RefObject;
};

export default function ToTopBtn({ elemRef }: ToTopBtnProps) {
  return (
    
         
  ); }

Etapa 5: teste adicionando novas postagens

Para testar a funcionalidade do botão "Rolar para o topo", precisamos adicionar novas postagens ao feed.
Para isso, usaremos useMutation do React Query para adicionar uma nova postagem ao servidor e revalidar nossa postList em cache após cada mutação.
Configuraremos uma mutação que nos permitirá criar uma nova postagem com dados aleatórios sempre que o usuário clicar em um botão.

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 (
    
         
  );

Conclusão

Neste tutorial, exploramos o poder do React Query por meio de um caso de uso real, destacando sua capacidade de ajudar os desenvolvedores a construir interfaces dinâmicas que melhoram a experiência do usuário.

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/mohamed_hammi/build-a-feed-page-using-react-query-1nbi?1 Se houver alguma violação, entre em contato com [email protected] para excluí-la
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3