Implementando Shimmer Effect no React Native

Há algum tempo o Facebook criou uma forma inusitada para indicar o carregamento de suas páginas, o chamado Shimmer Effect, que nada mais é que a exibição de um esqueleto da página em forma de animação no lugar de um Spinner ou uma Barra de Progresso, no React Native utilizaremos o react-native-shimmer-placeholder que dará uma melhora tanto no Design quanto na Usabilidade do nosso app.

Spinner vs. Shimmer

O Shimmer Effect é uma alternativa muito efetiva em relação ao loading tradicional pois permite que sejam criadas Skeletons Screens, que são as páginas onde enquanto o conteúdo é carregado de modo assíncrono o Shimmer está aparecendo, e ele dá um feedback bacana para o usuário, trazendo as seguintes vantagens:

  • Faz com que o usuário perceba que a página/tela carrega rápido;
  • Acaba com a surpresa sobre a interface;
  • Carregamento gradual da interface;
  • Indicação clara de progresso;
  • Mostra exatamente o que já foi carregado e o que ainda tem para carregar.

E nesse post vou te mostrar como implementar esse efeito fantástico no seu aplicativo para melhorar a experiência para o usuário final, algumas empresas famosas que utilizam essa técnica são o Google, Facebook, Medium e Instagram.

Então chega de papo e vamos à criação do projeto \o/

Criando o projeto React Native

Para iniciar o projeto você pode utilizar o React Native CLI, com ele instalado basta executar o comando:

react-native init ShimmerPlaceholder

Com o projeto criado instale o react-native-shimmer-placeholder e também uma dependência dele que precisa ser instalada manualmente, a react-native-linear-gradient:

yarn add react-native-linear-gradient
yarn add react-native-shimmer-placeholder
// npm install react-native-linear-gradient
// npm install react-native-shimmer-placeholder

E como o Linear Gradient utiliza de recursos nativos do dispositivo tem que ser feito o link entre o Javascript e o Código Nativo, e para isso basta executar:

react-native link react-native-linear-gradient

Nesse ponto você já está com sua aplicação pré-configurada e pronta para usar o Shimmer Effect, caso você tenha algum problema com a criação ou instalação dos pacotes, pode consultar a estrutura inicial nesse link.

Aplicando o Shimmer Placeholder


Antes de começarmos com o código em React Native, caso você ainda não conheça o framework, ou quer reforçar seus conhecimentos em Javascripte ES6/ES7/ ES8, dê uma olhada nos nossos minicursos gratuitos.


Será utilizado como referência a estrutura da página do Facebook, como essa abaixo:

Para focar apenas no uso da lib não serão os componentes da Barra de Busca e do TabMenu na parte inferior, para criar a estrutura inicial da página pronta para receber o conteúdo com o Shimmer Effect será editado o conteúdo do App.js, deixando-o da seguinte maneira:

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.searchBar} />
        <View style={styles.content}></View>
        <View style={styles.menuBar} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
  searchBar: {
    height: 54,
    backgroundColor: '#3b5998',
  },
  content: {
    flex: 1,
  },
  menuBar: {
    height: 54,
    backgroundColor: '#edeef1',
  }
});

Agora sim serão criadas as funções responsáveis por criar o esqueleto da página.

O primeiro passo é importar o react-native-shimmer-placeholder no começo do código, para isso basta importar ele dessa maneira:

import ShimmerPlaceHolder from 'react-native-shimmer-placeholder';

Com ele importado você pode criar o state que irá conter 3 variáveis booleanas que serão as responsáveis por dizer ao código quando deve ser renderizado o efeito ou o conteúdo devido da página, você pode criá-lo entre a declaração da classe do componente e o método render, o state ficou assim:

state = {
  visible: false,
  userImageVisible: false,
  postImageVisible: false,
}

Foram criadas 2 variáveis para as imagens pois será adotada uma abordagem diferente no carregamento delas, ao invés de serem exibidas junto com o conteúdo elas serão exibidas assim que forem carregadas.


Quer ver mais sobre o que você pode fazer com imagens na sua aplicação para melhorar a usabilidade? Corre lá dar uma olhada nesse post do Diego sobre Lazy Loading 😉


O próximo passo é criar o render do componente, para modularizar um pouco retirei a renderização dos componentes do método render e passei para uma função, portanto o render ficou assim:

render() {
  return (
    <View style={styles.container}>
      <View style={styles.searchBar} />
      { this.renderRows(3) }
      <View style={styles.menuBar} />
    </View>
  );
}

E como o estilo ficou um pouco extenso, para não postá-lo e apenas estender o post deixei ele disponível nesse link para vocês estilizarem a aplicação, basta copiar o código do link e inserir na const styles no final do componente App.


Antes de ir para a última parte (finalmente), a função que foi criada, a renderRows, será a responsável por retornar toda a estrutura da página, e o número passado para ela como parâmetro é a quantidade de componentes que ela vai renderizar, no nosso caso foi passado 3 para que ela renderize 3 posts.

E sobre a implementação da função renderRows, assim como o estilo ficou bastante extensa, e é por isso que disponibilizei ela nesse link, para inseri-la no nosso componente basta copiar o código do link e inseri-lo entre o state e o método render do componente App, abaixo darei uma breve explicação do funcionamento dela e do uso do componente ShimmerPlaceholder.

No começo da função há um laço de repetição para garantir que serão criados os componentes de acordo com o número passado por parâmetro, e dentro desse laço você verá em vários lugares o seguinte código:

<ShimmerPlaceHolder
  style={styles.shimmerComponent}
  autoRun={true}
  visible={this.state.visible}
>
  <Text></Text>
</ShimmerPlaceHolder>

Esse é o componente disponibilizado pela lib react-native-shimmer-placeholder para criar o efeito de carregamento, as props que foram usadas são a autoRun, que indica que assim que o componente for instanciado o efeito será iniciado, e a visible, que indica se o que será mostrado é a animação do componente ou o conteúdo de fato. Para ver todas as props disponíveis você pode acessar esse link.

E a última coisa a se fazer é inserir dentro do componentDidMount uma função para testar o funcionamento, pois enquanto os states estiverem com o valor false somente o efeito será mostrado, para isso você pode criar uma função para mudar esse valor depois de 2,5 segundos, ficando assim:

componentDidMount() {
  setTimeout(() => this.setState({ visible: !this.state.visible }), 2500);
}

Com tudo isso feito basta rodar o projeto e voilà, tudo deve estar funcionando corretamente.

Caso você tenha algum problema, dúvida ou seu projeto não esteja funcionando corretamente você pode acessar o código completo nesse link e comparar com o seu 😉

Conclusão

E chegamos ao final de mais um post, e nesse post mostrei uma alternativa ao Spinner que vem ganhando bastante espaço no desenvolvimento de aplicativos e sistemas web por proporcionar uma usabilidade e design mais agradável ao usuário.

Se você chegou até aqui desce mais um pouquinho e deixa seu comentário de sugestão ou crítica sobre o post 😉 É através do seu feedback que podemos cada vez melhorar mais e mais.

E por hoje é isso, um abraço!