Introdução
Quando acessamos uma página na web, o que esperamos é uma resposta instantânea ou o mais rápido possível. Porém, com as abordagens tradicionais que utilizam spinners, ou até mesmo que não mostram nenhuma resposta na tela enquanto os dados são carregados, isto geralmente não ocorre. Muitas vezes ficamos esperando, recarregamos a página, e não temos nenhum feedback da aplicação até que os dados sejam carregados.
Para resolver este problema, foi criado o skeleton loading. O skeleton loading é uma abordagem que visa melhorar a experiência do usuário exibindo elementos de carregamento que são similares ao conteúdo real que vai ser apresentado quando todos os dados carregarem.
Implementação no ReactJS
Agora que já entendemos o conceito e o motivo de utilizar skeleton loading, vamos para a prática.
Para implementar esta funcionalidade em uma aplicação ReactJS, vamos usar o pacote react-loading-skeleton.
Instalação
Com o NPM, use o comando abaixo para instalar o pacote (dentro da pasta do projeto):
npm install react-loading-skeleton
Já se estiver usando o yarn, use o seguinte comando:
yarn add react-loading-skeleton
Estado de loading e pegando dados da API
Para checar se os dados da nossa aplicação estão sendo carregados ou não, vamos criar um estado chamado loading
e setar o mesmo true
por padrão. Também vamos criar um estado data
para armazenar nossos dados
import React, { useEffect, useState } from 'react';
function Component() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
return <h1>Skeleton Loading</h1>
}
export default Component;
Agora, utilizando o hook useEffect
, vamos fazer a chamada a API, e, logo após isso, setar o loading
como false
import React, { useEffect, useState } from 'react';
import api from '../../../services/api';
function Component() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const timer = setTimeout(() => {
api.get('data').then(response => {
setData(response.data);
});
setLoading(false);
}, 3000);
return () => clearTimeout(timer);
}, []);
return <h1>Skeleton Loading</h1>
}
export default Component;
Como estamos em ambiente de desenvolvimento, usamos a função setTimeout
para que possamos ver as mudanças. É importante que você remova em produção.
Criando componente skeleton
Para fazer o skeleton, vamos criar um componente separado. É neste componente que importaremos o pacote que instalamos anteriormente
import React from 'react';
import Skeleton from "react-loading-skeleton";
function ComponentSkeleton() {
...
}
export default ComponentSkeleton;
Agora vamos usar o componente <Skeleton />
para montar nosso layout
import React from 'react';
import Skeleton from "react-loading-skeleton";
import './styles.css';
function ComponentSkeleton() {
<div className="skeleton-container">
<div className="skeleton-title">
<Skeleton height={28} width={300} />
</div>
<ul>
{Array(8)
.fill()
.map((item, index) => (
<li key={index}>
<div className="item-group">
<div className="skeleton-item">
<Skeleton height={20} width={`100%`} />
</div>
<div className="skeleton-item">
<Skeleton height={20} width={`100%`} />
</div>
</div>
<div className="item-group">
<div className="skeleton-item">
<Skeleton height={20} width={`100%`} />
</div>
<div className="skeleton-item">
<Skeleton height={20} width={`100%`} />
</div>
</div>
<div className="item-group">
<div className="skeleton-item">
<Skeleton height={20} width={`100%`} />
</div>
<div className="skeleton-item">
<Skeleton height={20} width={`100%`} />
</div>
</div>
</li>
))}
</ul>
</div>
}
export default ComponentSkeleton;
Com as propriedades width
e height
ajustamos a largura e a altura. Você também pode utilizar outras propriedades como count
, para a repetição automática, ou duration
, para setar a duração da animação. Caso queira saber mais, confira a documentação do pacote no GitHub.
Caso queira alterar coisas como o espaçamento desses elementos, você pode coloca-los dentro de divs e estilizar no CSS.
Checando se os dados já foram carregados ou não
Voltando ao nosso componente principal, precisamos verificar se os dados já foram carregados ou não. Para isso vamos usar o estado loading
que criamos anteriormente
import React, { useEffect, useState } from 'react';
import ComponentSkeleton from '../ComponentSkeleton';
import api from '../../../services/api';
function Component() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const timer = setTimeout(() => {
api.get('data').then(response => {
setData(response.data);
});
setLoading(false);
}, 3000);
return () => clearTimeout(timer);
}, []);
return (
<div className="container">
{loading && <IncidentSkeleton />}
{!loading &&
<>
<h1>Skeleton Loading</h1>
<ul>
{data.map(item => (
<li key={item.id}>
<strong>TÍTULO:</strong>
<p>{item.title}</p>
<strong>DESCRIÇÃO:</strong>
<p>{item.description}</p>
<strong>VALOR:</strong>
<p>{item.value}</p>
</li>
))}
</ul>
</>
}
</div>
);
}
export default Component;
Abaixo do container
estamos dizendo que, se o loading
for true
, mostre o skeleton. Logo abaixo estamos dizendo o contrário, se o loading
for false
, mostre os dados vindos da API.
Alternativas
Além do react-loading-skeleton, também temos outras alternativas como o react-content-loader e o react-loading-screen. Caso queira saber as vantagens e desvantagens de cada um, acesse este artigo.
Conclusão
Esta é uma solução que melhora muito a experiência do usuário, reduzindo a frustração que as telas de loading causam, além de ter uma implementação extremamente simples. Neste artigo usamos um pacote para facilitar o processo, mas você também pode fazer tudo com CSS se quiser.
Caso queira, vocẽ pode acessar o código completo da aplicação no GitHub.
Top comments (0)