As aplicações que exibem grandes quantidades de dados na forma de uma lista ou tabela, podem implementar a paginação para dividir os dados em uma sequência de páginas. Em vez de buscar grandes quantidades de dados de uma API do servidor, a paginação carrega dados sob demanda, diminuindo o tempo de carregamento e melhorando a interface do usuário geral.
Embora existam muitas bibliotecas disponíveis para implementar a paginação, algumas são um pouco pesadas, prejudicando o desempenho geral da sua aplicação. Neste artigo, criaremos um componente de paginação reutilizável usando React Hooks.
Como exemplo, exibiremos a lista de passageiros na imagem abaixo, usando paginação.
O que abordaremos neste artigo:
- Hook useSate
- Hook useEffect
- Configurando o projeto
- Criar um componente de paginação
- Usando o componente de paginação
Antes de entrar na implementação, deixe-me apresentar dois React Hooks que usaremos neste artigo.
Hook useState
Se você quiser adicionar estado ao seu componente funcional, o Hook UseState
fará o trabalho. Considere o exemplo abaixo:
// uma nova variável de estado chamada "currentPage"
const [currentPage, setCurrentPage] = useState(1);
O useState
ajuda a preservar os valores entre as chamadas de função. Leva um único argumento, que é o estado inicial. No exemplo acima, a variável currentPage
é definida como padrão 1
. O useState
retornará um par de valores, sendo o primeiro o estado da variável e o segundo, a função para manipular o estado.
Usaremos o Hook useState
para manter o estado da página atual, os limites mínimo e máximo da página, bem como manter os dados de resposta da API do passageiro.
Hook useEffect
Se você quiser executar quaisquer efeitos colaterais, como busca de dados, manipulação de DOM ou inscrição e cancelamento de inscrição em eventos, o useEffect
o ajudará a:
useEffect (()=>{ // chama rest api },[]);
O React tem acesso ao estado do seu componente, portanto, ele basicamente lembrará a função que você passou e a invocará após as atualizações do DOM. Usamos o Hook useEffect
para buscar dados de passageiros da API REST.
Configurando o projeto
Nosso objetivo é exibir a lista de passageiros com paginação, então usaremos a API REST gratuita para fornecer uma lista de dados de passageiros. Comece criando uma nova aplicação React usando o comando Create React App abaixo:
npx create-react-app pagination-tutorial
Remova todo o conteúdo padrão do arquivo App.js
. Incluiremos nossos componentes aqui mais tarde. O arquivo final deve se parecer com o código abaixo:
import './App.css';
function App() {
return (
<div className="App">
<div className="App-header">
// inclua o componente Passenger, que criamos no final
do artigo
</div>
</div>
);
}
export default App;
Agora, podemos executar a aplicação com o comando abaixo:
yarn start
Criando um componente de paginação
O componente funcional permite dividir a interface do usuário em partes independentes e reutilizáveis. Usaremos um componente funcional que possui um único argumento contendo props para o componente. Antes de criar nosso componente de paginação, vamos esclarecer alguns dos poucos termos usados no restante do artigo.
- Página atual: representa a posição do usuário na página
- Limite máximo de páginas: representa o limite superior da página
- Limite mínimo de página: representa o limite inferior da página
Vá para a pasta src
e crie um novo arquivo chamado: Pagination.js
import React from 'react';
const Pagination = (props)=> {
return(
<div>
</div>
)
}
export default Pagination;
Como estamos criando um componente reutilizável para paginação, suponha que o componente obtenha todos os dados do componente pai usando props. Nosso objetivo é criar uma saída como na imagem abaixo:
Inicialize os termos que discutimos na seção anterior:
// init
const { currentPage, maxPageLimit, minPageLimit} = props;
const totalPages = props.response.totalPages-1;
const data = props.response.data;
Agora, para inserir o número total de páginas, criaremos os números das páginas a partir de 1. O limite será baseado nos limites máximo e mínimo de páginas:
Construa o array de páginas, que conterá todos os números desde 1 até o total de páginas:
// construir um array com a quantidade de páginas com base no número total de páginas
const pages = [];
for (let i=1; i <= totalPages; i++) {
pages.push(i);
}
Para criar a interface do usuário com base no número de páginas que estão dentro dos limites mínimo e máximo de páginas, percorra a array de páginas construída com a etapa acima. Se a condição de interação corresponder á página atual, torne-a ativa:
const pageNumbers = pages.map(page => {
if(page <= maxPageLimit && page > minPageLimit) {
return(
<li key={page} id={page} onClick={handlePageClick}
className={currentPage===page ? 'active' : null}>
{page}
</li>
);
} else {
return null;
}
}
);
Em seguida, criaremos reticências ...
, que aparecem quando há mais páginas do que a página atual á esquerda ou á direita. Ao clicar nas reticências, o usuário pode ir para o grupo de páginas anterior ou seguinte. Você pode vê-los na imagem abaixo, destacados em verde:
// page ellipses
let pageIncrementEllipses = null;
if(pages.length > maxPageLimit) {
pageIncrementEllipses = <li onClick={handleNextClick}>…</li>
}
let pageDecremenEllipses = null;
if(minPageLimit >=1){
pageDecremenEllipses = <li onClick={handlePrevClick}>…</li>
}
const renderData = (data)=>{
Vamos renderizar nossos passageiros em um formato de lista. No código abaixo, estou mostrando o ID do passageiro e o nome da companhia aérea utilizada por cada passageiro:
return(
<ul>
{data.map((d)=>
<li key={d['_id']}> The passenger having id {d['_id'].slice(d['_id'].length-5)} using {d.airline[0].name} airlines</li>)
}
</ul>
)
}
Em seguida, combinaremos todos os elementos da interface do usuário e os retornaremos em nosso componente funcional, junto com os botões Anterior e Próximo.
Ao clicar em Anterior, o usuário navega para a página anterior. Ao clicar em Próximo, o usuário navega para a próxima página. Os elementos da interface do usuário são alinhados da seguinte maneira:
Passenger’s data
2. Pager
1. Prev button
2. Page decrement ellipses
3. Page numbers with current page selection
4. Page increment ellipses
5. Next button
return (
<div className="main">
<div className="mainData">
{renderData(data)}
</div>
<ul className="pageNumbers">
<li>
<button onClick={handlePrevClick} disabled={currentPage === pages[0]}>Prev</button>
</li>
{pageDecremenEllipses}
{pageNumbers}
{pageIncrementEllipses}
<li>
<button onClick={handleNextClick} disabled={currentPage === pages[pages.length-1]}>Next</button>
</li>
</ul>
</div>
)
Até agora, criamos a IU, que inclui eventos como clique na página, clique anterior e próximo clique. Agora, vamos vincular todos os eventos:
const handlePrevClick = ()=>{
props.onPrevClick();
}
const handleNextClick = ()=>{
props.onNextClick();
}
const handlePageClick = (e)=>{
props.onPageChange(Number(e.target.id));
}
Usando o componente de paginação
Agora, vamos navegar até o componente pai, que é o componente Passengers
, responsável por buscar os dados do passageiro e definir as props de paginação. Use o componente Pagination
criado acima nesse componente.
Para criar o componente Passengers
, primeiro inicialize o estado. Você pode consultar as variáveis de estado abaixo. Em termos simples, mostraremos o número de páginas começando do 1
ao 5
. Iniciamos os limites mínimo e máximo de páginas com 0
e 5
, respectivamente.
Definimos a página atual como 1
, o que significa que o usuário estará na primeira página. Definindo os dados do passageiro como um array vazio, determinamos que buscaremos os dados nas próximas etapas. O limite de páginas, 5
, informa que mostraremos apenas cinco páginas na UI:
const pageNumberLimit = 5;
const [passengersData, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const [maxPageLimit, setMaxPageLimit] = useState(5);
const [minPageLimit, setMinPageLimit] = useState(0);
Quando a página atual mudar, buscaremos os dados do passageiro de nossa API com o Hook useEffect
, mantendo-os na variável de estado passagenrsData
:
useEffect(()=>{
setLoading(true);
fetch(`https://api.instantwebtools.net/v1/passenger?currentPage=${currentPage}&size=5`)
.then((response) => response.json())
.then((json) => { setData(json); setLoading(false);});
},[currentPage]);
A etapa principal dessa paginação completa é atualizar a página mínima, máxima e atual, que são atualizadas na mudança de página, no clique anterior e no próximo clique.
Clique anterior
Suponha que você esteja na sexta página do nosso componente de paginação. Se você clicar no botão Anterior, será direcionado para a quinta página e os limites de página deverão ser redefinidos para 1 e 5.
Para obter o exemplo acima, atualizaremos os limites mínimo e máximo de página, somente se a página anterior não estiver no intervalo de páginas atual. O resto obtido após a divisão da página anterior pelo número de página, deve ser zero.
Por exemplo, considere que o limite máximo de páginas deve ser igual ao limite atual, menos o limite de número de páginas. No nosso exemplo na imagem acima, 10 menos cinco é igual a cinco.
Para o limite mínimo de páginas, subtraímos o limite do número de páginas, pelo limite mínimo atual. Em nosso exemplo, calculamos que seis menos cinco é igual a um. Lembre-se que a página atual, é a página anterior menos 1
.
Clique próximo
Exploraremos o clique próximo, como uma alternância do exemplo anterior. Suponha que você esteja na quinta página agora. Clique em Próximo e você deve navegar para a sexta página. Os limites da página devem estar entre 6
e 10
.
Assim como no clique anterior, só podemos atingir o cenário acima atualizando o limite mínimo e máximo de páginas. Os limites mínimo e máximo de páginas, são atualizados apenas quando a próxima página é maior que o limite máximo de páginas atual:
Para calcular o limite máximo de páginas, adicionamos o limite máximo atual ao limite de número de páginas. Em nosso exemplo, somamos cinco e cinco para igualar 10.
O limite mínimo de páginas é o limite mínimo atual mais o limite do número de páginas. No nosso exemplo, um mais cinco é igual a seis. A página atual é a página anterior mais uma.
Mudança de página
Ao clicar em qualquer número de página, atualize a página atual para o número específico. Abaixo está o trecho de código para todos os principais eventos:
const onPageChange= (pageNumber)=>{
setCurrentPage(pageNumber);
}
const onPrevClick = ()=>{
if((currentPage-1) % pageNumberLimit === 0){
setMaxPageLimit(maxPageLimit - pageNumberLimit);
setMinPageLimit(minPageLimit - pageNumberLimit);
}
setCurrentPage(prev=> prev-1);
}
const onNextClick = ()=>{
if(currentPage+1 > maxPageLimit){
setMaxPageLimit(maxPageLimit + pageNumberLimit);
setMinPageLimit(minPageLimit + pageNumberLimit);
}
setCurrentPage(prev=>prev+1);
}
Para criar a UI para passageiros com paginação, vamos combinar todos os atributos necessários e enviá-los como props para o componente de paginação:
const paginationAttributes = {
currentPage,
maxPageLimit,
minPageLimit,
response: passengersData,
};
return(
<div>
<h2>Passenger List</h2>
{!loading ? <Pagination {...paginationAttributes}
onPrevClick={onPrevClick}
onNextClick={onNextClick}
onPageChange={onPageChange}/>
: <div> Loading... </div>
}
</div>
)
Agora, construímos os componentes pai e filho. Você está pronto para usar o componente pai em qualquer lugar da aplicação.
Conclusão
Neste tutorial, criamos um componente de paginação enviando a página atual, limite máximo de página, limite mínimo de página e outros eventos de página como props para o componente. Usamos React Hooks para gerenciamento de estado e busca de dados.
Enquanto desenvolvemos nossa aplicação de exemplo em React, você pode aplicar a mesma lógica a qualquer projeto. Espero que você tenha aprendido algo novo! Certifique-se de deixar um comentário se tiver alguma dúvida.
Top comments (0)