Criando um componente esqueleto para simular conteúdo enquanto busca ou prepara dados para tela

Fabio Mazucato
9 min readFeb 28, 2021

Fala galera!!!

Este é meu primeiro artigo na comunidade, é sobre React Native e nele eu quero falar sobre meu aprendizado e minha ideia. Vamos lá?

Fiz algumas pesquisas procurando lib's, algo prático de usar e confiável para montar esqueletos de tela e usar no loading, encontrei algumas mas não curti e dando aquela fuçada para entender o código eu resolvi fazer meu componente. Por que não?

É isso mesmo, eu resolvi criar meu componente aplicando minhas ideias.

Botando no papel, eu precisava criar algo simples de usar, controlando o tamanho, espaçamento e arredondamento das bordas.

Pronto, essa era a ideia!! Criar um componente oscilando a cor e recebendo propriedades para largura, altura, margem e arredondamento da borda.
Com esses valores seria possível estilizar meu componente e torna-lo dinâmico para montar qualquer tela com esqueleto no projeto.

Primeiro eu decidir fazer funcionar de forma estática para ver se iria dar certo, depois fui dando aquele talento e jogando a cereja do bolo.
Repo no github

Vou dividir minha experiência em 2 partes:

1 — Estrutura do componente / Design e estilização;
2 — Animação.

Antes de começar, vamos criar um projeto e instalar as dependências:

Parte 1 — Estrutura do componente / Design e estilização:

1 — Homepage do RN ao criar um projeto novo / 2 — Tela usando o componente simulando área do conteúdo

Eu gosto muito de separar as coisas, em minha estrutura de pasta eu crio 3 arquivos:

1 — index (a parte funcional, apenas regras);
2 — View (a parte visual, apenas elementos);
3 — styles (a parte de estilização da tela).

Bora meter a mão na massa, o componente é muito simples e nessa primeira parte vou mostrar como criei a estrutura e estilização. Não vou conseguir explicar neste artigo sobre a estrutura, mas pretendo descrever em outro artigo, como eu aprendi e qual tem sido minha experiência.

Na construção do componente, eu definir as propriedades abaixo para controlar a estilização, assim conseguiremos usar dinamicamente de diversas formas.

A propriedade dimensions é um vetor de 2 posições para controlar as dimensões [width, height]. Ele recebe o valor da altura e largura em número para pixel ou string para porcentagem.

A propriedade circle está definida como nulo, significa que é um elemento sem borda arredondada, para arredondar a borda basta passar o valor em número.
É possível até formar um círculo no elemento.

A propriedade margin é um vetor de 2 posições para controlar o espaçamento da área ou entre eles [horizontal, vertical], o valor é número.

Veja neste exemplo como criei minha estrutura de pastas:

Estrutura de pastas

Dentro da pasta ‘src/components/’ criei uma nova pasta e chamei de ‘skeleton’.

Este é o arquivo index.js, nele vamos definir regras e simplificar o envio das variáveis e métodos, já definimos valores default para as propriedades que serão recebidas, caso não sejam enviados garantimos que não ocorrerá problemas com nosso componente.

  • Usaremos estes valores para estilizar nosso componente.
Observe que ao criar o elemento "createElement" da View, um objeto é enviado com as propriedades que a View espera receber.

Este é o arquivo view.js, nele estão somente os elementos. Vamos receber as propriedades enviadas através do container (index.js) para controlar as dimensões, margem e arredondamento da borda do elemento.

Importamos o elemento SkeletonArea do arquivo styles porque estamos usando Styled Components

Este é o arquivo styles.js, nele estão a estilização dos elementos que vão compor nossa tela, como View, Text e outros elementos do React Native através do Styles Components. Eu gosto de exportar estes elementos com nomes específicos para a view ficar mais elegante e organizada.

Observe que na constante SkeletonArea, recebemos algumas propriedades para tornar nossa estilização dinâmica, possibilitando várias formas de altura, largura, espaçamento e arredondamento da borda. Entenda como isso funciona clicando aqui.

Bom, vou tentar explicar o que fiz aqui. Lá no arquivo view,js no elemento SkeletonArea estamos enviando a propriedade width e resgatamos seu valor no arquivo styles.js, no contexto do Styled Components na constante SkeletonArea. Simplifiquei usando a expressão de desestruturação do Javascript que possibilita extrair variáveis de um objeto, veja como isso funciona clicando aqui. Ao fazer isso eu consigo extrair a variável que eu desejo, meu código fica mais limpo e mais claro (eu acredito nisso rsrsrs).

No caso da variável width e height, como podemos enviar o valor como número ou string, exemplo 10 ou '10%', eu preciso verificar o que estou recebendo para determinar como imprimir o valor de cada dimensão, seja em pixel ou porcentagem. (Pode ser que esta não seja a melhor forma).

A propriedade margin e border-radius, segue a mesma ideia, faço a desestruturação da variável e aplico ao valor que desejo estilizar meu componente.

Vamos utilizar nosso componente

Agora vamos fazer isso funcionar criando uma tela que será o esqueleto do layout da homepage de Bem-Vindo quando criamos o APP com o React Native. Se tiver alguma dúvida, corre lá no git no repo aqui e veja como ficou. Se curtiu, dá Star lá que ajuda o parceiro kkkkkkk

Dentro da pasta ‘src/screens/home/components’ criei uma nova pasta e chamei de ‘homeLoading’, dentro dela eu criei mais 2 arquivos, index.js e styles.js. Como essa tela é bem simples, eu não crio o arquivo view.js.

No arquivo index.js, vamos utilizar o Flatlist para renderizar uma lista com 3 seções de conteúdo utilizando o componente Skeleton com tamanhos, margem e bordas arredondadas de formas diferentes, que simula exatamente a lista de seções de conteúdo de texto da homepage.

A construção dessa tela é um modelo de como podemos criar telas simulando as áreas de conteúdo usando o componente Skeleton. Para manter a organização do nosso projeto, criei dentro da pasta screens/home outra pasta components para armazenar somente os componentes que serão utilizados na tela home.

Este é o arquivo styles.js, nele estão estilizados os elementos View, Text e outros do React Native através do Styles Componentes e exportados com nomes específicos para a view ficar mais elegante e organizada.

Tudo pronto, vamos ver nossa tela em ação? Lembrando que até agora nosso componente não tem animação, mas, vamos conseguir vê-lo simulando as áreas de conteúdo de forma estática conforme a imagem abaixo.

Para simular a exibição da tela de loading e em seguida o conteúdo da homepage, usei um intervalo de tempo para manipular um estado que vai controlar a renderização desses elementos. Para entender como usar o intervalo de tempo, clique aqui.

Segue abaixo a homepage do React Native organizada com a estrutura definida no projeto.

Este é o arquivo index.js da pasta 'src/screens/home', nele vamos criar uma função e chamar de handleTimeLoading, que será executado através do Effect Hook, o setTimeout vai criar um intervalo de tempo de 3 segundos e em seguida vai executar o setIsloading para alterar o valor do State do Hook isLoading de true para false.

Observe que ao criar o elemento da View, um objeto é enviado com as propriedades que a View espera receber.

Este é o arquivo styles.js da pasta ‘src/screens/home’.

Este é o arquivo view.js da pasta ‘src/screens/home’, nele adicionamos uma condição usando a propriedade isLoading que sofrerá uma mutação de valor e com isso conseguiremos exibir primeiro nossa tela de loading e depois o conteúdo da homepage.

Parte 2 — Animação:

Agora que nosso projeto está organizado, a tela de loading da homepage funcionou usando o componente Skeleton, vamos botar a cereja no bolo com a animação. Uhuuuuuuuuu

Precisamos tornar o componente usável em qualquer cor que seja o background da tela, tendo em mente essa premissa, a melhor forma é oscilar a cor indo de 0% a 100%. Isso parece ser a forma mais prática de criar esta animação sem ter problemas com o background.

Precisamos criar uma estrutura de repetição contínua e determinar as ações que essa animação deve ter. Agora só precisamos entender como fazer isso usando o Animated do React Native

Resultado final com Animated

Entendendo um pouco do animated, vamos precisar usar o loop() para estrutura de repetição e sequence() para ordenar as ações da animação com o timing() que contém os valores e propriedades de cada ação. Tudo isso vai compor a nossa animação para oscilar de 0% a 100% a cor.

Este é o resultado final do arquivo index.js da pasta ‘src/components/skeleton’.

Você pode substituir seu arquivo anterior por esse e seguir os passos abaixo para entender as modificações que vamos fazer nesse arquivo comparado a sua primeira versão.

  1. Linha 2: importamos o Animated e o Easing do React Native
  2. Linha 9: declaramos um estado para armazenar os valores em cada ação da animação, conforme esse estado altera a cor vai mudar entre 0% e 100% de transparência;
  3. Linha 11 até 26: criamos um loop, a ordem e cada ação com suas propriedades e valores, observe a prop toValue em cada ordem, na primeira ação o valor é 0.8 que vai representar a cor em 100% e na segunda ação o valor é 0.3 que vai representar a cor em 0% (transparente).
  4. Linha 29: precisamos enviar para view o estado animated que criamos.

Antes de chegar na View, precisamos fazer algumas mudanças em nosso estilo para usar o Animated com Styled Components. O Animated cria o seu elemento View com Animated.View, como nós estamos usando Styled Componentes e passamos para View nossos elementos estilizado, precisamos usar o createAnimatedComponent para tornar animável nosso novo elemento do animated e passar para view o mais elegante e organizado possível.

Este é o resultado final do arquivo styles.js da pasta ‘src/components/skeleton’.

Você pode substituir seu arquivo anterior por esse e seguir os passos abaixo para entender as modificações que vamos fazer nesse arquivo comparado a sua primeira versão.

  1. Linha 2: importamos o Animated do React Native;
  2. Linha 6: alteramos o nome anterior (SkeletonArea) para (AnimatedViewStyle);
  3. Linha 3: adicionamos ao nosso estilo a propriedade do css opacity, nessa propriedade vamos receber o valor do nosso estado animated e manipular a opacidade conforme o valor do estado.
  4. Linha 16: vamos criar o elemento animado e estilizado com o createAnimatedComponent e passar para View.

Agora vamos ao último passo da nossa animação!!!

Este é o resultado final do arquivo view.js da pasta ‘src/components/skeleton’.

Você pode substituir seu arquivo anterior por esse e seguir os passos abaixo para entender as modificações que vamos fazer nesse arquivo comparado a sua primeira versão.

  1. Linha 3: vamos importar do style o elemento "AnimatedView" no lugar do "SkeletonArea"
  2. Linha 7: lembra que na index enviamos via props para view o animation?Então, vamos extrair da props o animation também;
  3. Linha 16: como fizemos na importação do style, precisamos alterar o nome do nosso elemento”SkeletonArea" para “AnimatedView”;
  4. Linha 17: precisamos enviar para nosso style o valor do animation na prop opacity.

Agora é só rodar e ver seu esqueleto de tela funcionando!!!

Este código funcionou muito bem para mim e espero que funcione para você também. Se isso te ajudou ou tem algum ponto que pode ajudar a melhorar, deixa ai nos comentários ou acessar o projeto lá no Github e manda ver também. Tenho certeza que a melhor forma que nós temos para melhorar e evoluir é retribuindo e contribuindo. Meu muito obrigado!!!

--

--