Como fazer um menu lateral customizado usando React native e React navigation 5
Tags: reactnative, typescript, sidemenu, react
Published: 2021-01-16 13:12:49

Há diversas formas de navegar por um aplicativo, o menu lateral é uma forma bastante conhecida, sendo um dos tipos mais encontrados em ferramentas mobile. Trabalhando como desenvolvedor não foi uma grande surpresa quando foi solicitado o desenvolvimento de tal mecanismo de navegação.

Porém, uma coisa que me surpreendeu foi a falta de informação sobre o tema na internet, principalmente sobre a nova versão do react navigation. Acabei passando horas pesquisando e filtrando informações para conseguir montar um mecanismo igual solicitado.

Para suprir a necessidade era necessário encontrar uma forma de deixar um item do menu com o estado de ativo, assim como  poder adicionar mais componentes visuais de forma a deixar a interface mais amigável.

Desta forma, resolvi escrever este artigo para mostrar a abordagem que foi utilizada para solucionar o problema, sendo aqui um compilado de todas as informações encontradas e usadas para desenvolver a solução.

## Iniciando o projeto e dependências usadas

Como o react native e suas dependências estão sempre evoluindo e mudando de versão, irei descrever como fiz as instalações e informar as versões instaladas no momento que este artigo foi escrito.

Primeiro, vamos usar o seguinte comando:

``` npx react-native init nome-do-seu-projeto --template react-native-template-typescript ```

Com esse comando você está iniciado o projeto usando o CI do react native assim como o template de typescript no projeto.

O segundo passo é instalar o styled component

```yarn add styled-components
yarn add @types/styled-components-react-native -D```

O terceiro passo é instalar as dependências do react navigation:

```yarn add @react-navigation/native```

E:

yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

Em seguida:

```yarn add @react-navigation/drawer```

Por último, como vou usar Icons na aplicação:

```yarn add react-native-vector-icons
yarn add @types/react-native-vector-icons -D```

Com isso, vamos ter todas as dependências para a execução do projeto descrito neste artigo.

Como prometido, a seguir tem todas as versões instaladas no projeto:

{% gist https://gist.github.com/EdnilsonCS/f964b08222c9586a71e801ed42af5542 %}

## Desenvolvimento da aplicação

### Instalação do React Native Vector Icon

Para android é necessário apenas abrir o arquivo android/app/build.gradle e adicionar a seguinte linha no final:

```apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"```

Já na plataforma IOS, abra o arquivo ios/NOMEDOPROJETO/info.plist e adicione a seguinte chave:

```
<key>UIAppFonts</key>
 <array>
 <string>AntDesign.ttf</string>
 <string>Entypo.ttf</string>
 <string>EvilIcons.ttf</string>
 <string>Feather.ttf</string>
 <string>FontAwesome.ttf</string>
 <string>FontAwesome5_Brands.ttf</string>
 <string>FontAwesome5_Regular.ttf</string>
 <string>FontAwesome5_Solid.ttf</string>
 <string>Foundation.ttf</string>
 <string>Ionicons.ttf</string>
 <string>MaterialIcons.ttf</string>
 <string>MaterialCommunityIcons.ttf</string>
 <string>SimpleLineIcons.ttf</string>
 <string>Octicons.ttf</string>
 <string>Zocial.ttf</string>
 </array>
```

### Estrutura do projeto

Primeiramente vamos criar uma pasta chamada src na raiz do projeto e criar um arquivo index com o seguinte conteúdo:

{% gist https://gist.github.com/EdnilsonCS/71d128247953cbd05653a75bbb03c196 %}

Como podemos perceber dentro deste arquivo foi importado as rotas da aplicação criada na pasta "routes", com arquivo principal com o seguinte conteúdo:

{% gist https://gist.github.com/EdnilsonCS/1952803683ab246ecc3b0befc78a853c %}

Aqui neste arquivo podemos tirar algumas informações interessante como:
* Declaramos duas rotas para as telas que serão criadas, a tela Home e a tela About;
* Passamos o componente do menu customizado(Drawer Content) para o Drawer.navigator através da propriedade drawerContent.

Já o componente DrawerContent é composto pelo seguinte código:

Arquivo Principal:
{% gist https://gist.github.com/EdnilsonCS/2ad3ed5bbad89842544a7b26ebdca5f7 %}

Arquivo de estilos:

{% gist https://gist.github.com/EdnilsonCS/96ed67c1225537752ddf49d779709a2b %}

Neste componente podemos tirar as seguintes informações principais:
* As propriedades passadas para o componente no arquivo de rotas é recebidas no componente com a tipagem "DrawerContentComponentProps" importado do @react-navigation/drawer.
* Os itens que serão exibidos no menu são declarados através de um array com o nome da rota, icon e titulo a serem exibidos na lateral do aplicativo.
O componente final que será exibido na lateral se chama MenuItem e que é gerado através do array de opções declarado.

O Componente MenuItem é composto pelo seguinte código:

Arquivo principal:
{% gist https://gist.github.com/EdnilsonCS/ad0b3a0b6ef05bc6875e31a3d4628680 %}

Arquivo de estilos:
{% gist https://gist.github.com/EdnilsonCS/96ed67c1225537752ddf49d779709a2b %}

Neste componente também tiramos algumas informações importantes, pois usamos de alguns conceitos não muito conhecido do react navigation, segue a explicação:
* A constante ActiveRouteName é recuperada através do valor do routeName que é passado pelo DrawerNavigation através das props dos componentes, sendo possível pesquisar o index correspondente na pilha de telas e pegar o nome exato da rota atual.
* Já a constante isActive faz uma simples comparação usando o valor da rota que foi passado como parâmetro para o componente com a ActiveRouteName encontrado.
* A função navigationToScreen faz uma validação verificando se a função de onPress foi enviada, navegando para a tela correspondente.

Para finalizar, vou mostrar como podemos abrir o menu lateral na tela e visualizar como vai ficar na aplicação.

Para isso eu criei duas telas e um componente de header, como as telas são praticamente iguais vou deixar apenas o código da tela Home e do componente Header:

Arquivo Principal da tela Home:
{% gist https://gist.github.com/EdnilsonCS/9f215b66f36409e6213b1077800ef1e3 %}

Arquivo de estilos da tela Home:
{% gist https://gist.github.com/EdnilsonCS/bc01a01dc50d973f2786d62c004ec0dd %}

No código da tela de home também temos mais algumas informações importantes sobre o menu lateral:
* A primeira é que para abrir, precisa usar o hook de navegação useNavigation().
* Se você não for adepto ao typescript poderá perceber algo estranho, que no caso é a tipagem das rotas que precisa ser passada como parâmetro para poder ter acesso às propriedades do DrawerNavigation.Header.

Por fim, o último componente:

Arquivo Principal do componente Header:
{% gist https://gist.github.com/EdnilsonCS/2dc0d1acb6ffdf97289c5170705d3cd7 %}

Arquivo de estilos do componente Header:
{% gist https://gist.github.com/EdnilsonCS/5c4814be9f329046e38b807777722fe8 %}

## Interface final
Abaixo, fica o exemplo de como o app deve ficar com o código compartilhado:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o0aeom70ooryvcsp4fj6.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dqkn1fx5c14fgzw8zorz.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0bs2sokadm0zojoru8iy.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/co1yzuatxdl1mkt0n8z1.png)

## Conclusão
Esse artigo teve como objetivo mostrar como criar um menu lateral usando o react navigation v5. Espero que eu tenha conseguindo mostrar de uma forma fácil, detalhada e objetiva como implementar essa funcionalidade tão pedida pelos designer.

Sinta-se à vontade para modificar o código e fazer as melhorias necessárias para sua aplicação.

E por fim, se achou esse artigo útil compartilhe nas redes sociais e para aquele seu amigo que está se aventurando no mundo do desenvolvimento mobile ou até mesmo para aqueles que não estão.

## Referências
Foto da capa by Joshua Aragon on Unsplash

[`React Native Docs`](https://reactnative.dev)
[`React Navigation V5 Docs`](https://reactnavigation.org/)
[`Styled Components Docs`](https://styled-components.com/docs)
[`React Typescript Docs`](https://www.typescriptlang.org/docs/handbook/react.html)
[`React native Vector Icons Docs`](https://github.com/oblador/react-native-vector-icons)
[`Typescript Docs`](https://www.typescriptlang.org/)