Gerenciando temas com Custom Hooks, React Context API e TypeScript em uma aplicação React Native

Gerenciando temas com Custom Hooks, React Context API e TypeScript em uma aplicação React Native

Luísa Barros. React Native é um framework JavaScript utilizado principalmente na construção de aplicações cross-platform para dispositivos móveis. O desenvolvimento de interfaces que captam a atenção do usuário envolve muitas variáveis, e uma delas é o conjunto de estilos que irá compor essa interface.

Nesse artigo, iremos detalhar a importância de um bom gerenciamento de estilos por meio de temas, fazendo o melhor uso do TypeScript, da React Hooks e Context  API e do Styled Components.

Os temas nos permitem padronizar e reutilizar estilos em vários componentes da aplicação e nada mais são do que simples objetos onde definimos as cores, tipografia, tamanhos, espaçamentos e diversas outras propriedades que constituem a UI do nosso aplicativo. Suas possibilidades de utilização visam:

  • manter a consistência da identidade de marca da aplicação;
  • facilitar a implementação de funcionalidades como modo claro e escuro;
  • customizar a aplicação de acordo com as preferências do usuário;
  • auxiliar na acessibilidade (tamanho de fontes, correção de cores, etc);

Então, ao invés de, por exemplo, passarmos o código hexadecimal de uma cor diretamente ao componente, o passaríamos através de um tema:

O exemplo anterior pode não ter esclarecido completamente a razão para o uso de temas, uma vez que parece estar gerando código adicional para um único uso. No entanto, imagine uma situação em que estamos lidando com uma aplicação que possui uma grande quantidade de componentes e a necessidade de alterar a cor de todos os textos no sistema. Nesse cenário, em vez de modificar cada componente individualmente, podemos simplesmente ajustar o tema.

Criando os objetos de tema

Inicialmente, vamos manter toda a lógica em um único arquivo mas, conforme o projeto escale, pode ser interessante criar uma pasta específica para definir as propriedades de cada objeto de tema. Antes disso, vamos determinar a tipagem do objeto, para que cada um possua os mesmos atributos e não haja nenhuma divergência. Aqui a grande estrela entra em jogo: o TypeScript. Criaremos, então, um type chamado Theme:

Nota: As 3 propriedades abaixo são apenas um exemplo, você pode criar as suas próprias. Caso utilize alguma biblioteca com componentes já pré-definidos como o Native Base, Material UI ou React Native Paper, é importante identificar na documentação a especificação que eles seguem, e criar o seu objeto de temas no mesmo formato. Assim, você pode fazer as customizações necessárias estendendo o Default Theme da própria biblioteca ou passar diretamente o objeto com as suas propriedades.

Para garantir a liberdade de podermos adicionar quantos temas quisermos, vamos criar um único objeto, que irá conter todos os temas. Ele será do tipo Record<Theme['mode'], Theme>, com chaves e valores de um tipo específico. No exemplo abaixo, a chave será do tipo 'LIGHT' | 'DARK' e o valor será do tipo Theme, que criamos logo acima:

Com o objeto de tema criado, podemos ir para os próximos passos: gerir a funcionalidade de troca de temas e deixá-lo disponível por toda a aplicação!

Criando um hook customizado: `useTheme`

Muitas bibliotecas possuem suporte para temas, o que nos possibilita gerenciá-los de forma mais prática. Dependendo da complexidade da aplicação e do acoplamento à bibliotecas de terceiros, pode ser conveniente utilizar os recursos exportados por elas, visto que requerem mínimas configurações para implementar. Porém, iremos criar o nosso próprio hook customizado! Isso nos garante total controle da estrutura, encapsulando a lógica de gestão dos temas em um único lugar, além de não depender de nenhuma biblioteca externa.

Um hook customizado nada mais é do que uma função que utiliza as funcionalidades de estado e ciclo de vida do React, nos permitindo criar snippets de código que podem facilmente ser compartilhados entre vários componentes. Ele precisa ter o prefixo 'use' + um nome iniciando com letra maiúscula (por exemplo, useTheme). O nosso hook vai retornar uma função chamada switchTheme, que irá alterar o tema atual, e o currentTheme - um estado com o objeto do tema que está sendo utilizado no momento.

Disponibilizando o `useTheme` com a Context API

Com o hook criado, precisamos deixá-lo acessível em qualquer local da aplicação. Para isso, utilizaremos a API de contexto nativa do React, a fim de deixar o objeto de tema e a função de alteração, que são exportados pelo hook, disponíveis globalmente. Primeiro, vamos criar o contexto e utilizar o useContext() no nosso hook customizado:

Se você prestou atenção no código acima, notou que lançamos um erro caso o contexto não esteja definido, exigindo que o hook seja usando dentro de um ThemeProvider. É dessa forma que o React gerencia o acesso aos contextos, e é justamente o Provider que associa um contexto a um determinado escopo. Portanto, agora iremos exportar o nosso Provider:

Prontinho! Tudo certo para conseguirmos utilizar o nosso tema na aplicação.

Utilizando o `useTheme`  🎉

Finalmente, podemos acessar as funcionalidades fornecidas pelo nosso hook customizado em qualquer componente funcional do sistema. Para isso, precisamos apenas importá-lo e invocá-lo:

No exemplo acima, utilizamos inline styles, porém o Styled Components nos permite criar componentes customizados usando uma sintaxe muito parecida com o que é utilizado na web, o CSS-in-JS. Caso estivéssemos utilizando o Provider da própria biblioteca, poderíamos apenas estender a interface DefaultTheme dela:

Porém, uma vez que criamos nosso próprio hook, precisamos passá-lo via props. Dessa forma, conseguimos acessar o nosso tema nos arquivos de estilização e usar o Typescript a nosso favor:

Conclusão

Neste artigo, exploramos a importância dos temas em aplicativos mobile e como podem melhorar a experiência do usuário. Desenvolvemos um hook customizado que permite um controle centralizado dos estilos, priorizando código limpo e reutilizável. Disponibilizamos esse hook globalmente pela aplicação com a React Context API, a partir de um Provider, podendo ser consumido tanto pelos componentes funcionais, quanto pelos arquivos de estilização. E, por fim, podemos ver como o TypeScript desempenhou um papel fundamental para definir estruturas de dados sólidas, garantindo a coesão dos atributos e propriedades em toda a aplicação. Espero muito que com essas ferramentas, você esteja mais capaz de criar aplicativos com interfaces visualmente consistentes e altamente personalizáveis.

Referências

https://reactnavigation.org/docs/themes
https://styled-components.com/docs/advanced#theming
https://react.dev/learn/passing-data-deeply-with-context

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.