Skip to content

idopterlabs/react-native-boilerplate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Idopterlabs React Native Boilerplate

image image image image
  • 🚀 Typescript
  • 🚀 Testes
  • 🚀 Controle de rotas
  • 🚀 Suporte a temas (light/dark)
  • 🚀 Design consolidado
  • 🚀 Splashscreen
  • 🚀 Serviços para HTTP Request e tratamento de erros
  • 🚀 Monitoramento de bugs via AppCenter
  • 🚀 CI via Gitlab

Sobre

Este boilerplate possuir uma base sólida para desenvolvimento de aplicativos mobile usando React Native. São fornecidos estrutura de pastas organizadas, dependências comuns usadas, controle de rotas de navegação, configuração de testes usando Jest e utilitários.

Inicializando um projeto

Pré-requisitos

  • NVM
  • Yarn
  • Cocoapods
  • JDK 11
  • Xcode
  • Android SDKs (Recomendado instalar via Android Studio)

Usando o Boilerplate

Há duas maneiras de usar esse boilerplate.

  1. Clonando o repositório e usando a react-native-rename ferramenta para troca o nome do app conforme o projeto que será desenvolvido.
  2. Inicializar um novo projeto react native pela ferramenta oficial e copiar os demais arquivos desse repositório, excerto o  package.json, app.json, android/ e ios/, e por final copiar as dependências que não estão inclusas no projeto oficial. Lembrando que algumas delas são necessárias aplicar configurações especias nas pastas designado de cada sistema operacional (android/ e ios/):

Configurações

Variável de Ambiente

As variáveis de ambiente devem ser colocadas no arquivo .env, um exemplo de como definir as variáveis usadas está localizado em .env.example, lembrando de que sempre que criar uma nova variável no projeto definir ela no .env.example também, para que outros membros possam ter conhecimento dela. Algumas regras para nomenclatura de variável:

  • Devem começar com "RN"
  • Usar estilo de nome de variável snake case
  • Usar somente letras maiúsculas e sem acentuação

Exemplos:

  • RN_MINHA_VARIAVEL
  • RN_USER_ID
  • RN_PASS

Por padrão todo projeto tem quatro variáveis:

  • RN_BASE_URL: Informar a URL base referente a URL de um serviço web que em algum momento o cliente pode ser redirecionado de dentro do app
  • RN_BASE_URL_API: Informar a URL base referente ao consumo de uma web API dedicado ao app
  • RN_ENV: O ambiente que está sendo usado, como, por exemplo: development, test, staging, production
  • RN_FEATURES_OFF: Informar quais funções vão ser desativado no app, essa env é opcional

Splashscreen

Para criar uma splashscreen você deve usar o generate-bootsplash, informado o caminho para a logo da splashscreen e a cor de fundo, exemplo:

yarn react-native generate-bootsplash src/assets/images/logoSplashScreen.png --background-color=ffffff --logo-width=100 --assets-path=src/assets --flavor=main

Uma segunda tela de abertura pode ser configurada em src/screens/SplashScreen (Recomendado deixar como Splashscreen nativo, para não ter efeito de "piscada de tela" entre as transições), essa não está limitada a apenas utilização de uma imagem, elementos como barra de carregamento podem ser adicionando. Essa tela é carregada após o SplashScreen nativo do sistema operacional (Android/iOS), essa tela em questão deve ser usado para esperar o carregamento ou verificação de dados do app, tal como se o usuário está autenticado.

Para mais informações de padrões da SplashScreen veja em Android Guide - Splash screens.

App Center

Usamos o AppCenter para gerar build e monitorar crash, devido isso você deverá fornecer o "APP SECRET" do projeto registrado no AppCenter em appcenter-config.json.

Folha de Estilo

O boilerplate é projetado para utiliza Styled Component e React Native Paper, a customização do app é feito através de configurações de estilo localizado em src/theme.

A principal dele é as cores (src/theme/colors.ts), nele está contido as cores a serem consumido no app, usado o sistema de cores do Material Design, devido isso é possível inclusive usar a ferramenta de customização de tema do Material Design: https://material.io/resources/color/. Caso o App tenha uma variente de modo escuro, suas cores podem ser definido em src/theme/colors.dark.ts.

Estrutura do Projeto


📦(root boilerplate)
┣ 📂.vscode (Configurações e extensões para o VSCode)
┣ 📂android (Configurações e código nativo referente ao Android)
┣ 📂ios (Configurações e código nativo referente ao iOS)
┣ 📂patches (Correções e melhoria dos pacotes usados no projeto)
┣ 📂src (Pastar principal do projeto)
┃ ┣ 📂assets (Arquivos estáticos)
┃ ┃ ┣ 📂fonts (Fontes)
┃ ┃ ┣ 📂images (Imagens .png, .jpg, etc)
┃ ┃ ┗ 📂svg (SVGs .svg)
┃ ┣ 📂components (Componentes usado no app)
┃ ┃ ┣ 📂[Nome do componente]
┃ ┃ ┃ ┣ 📜index.tsx (Implementação do componente)
┃ ┃ ┃ ┣ 📜index.spec.tsx (Teste do componente)
┃ ┃ ┃ ┗ 📜styles.ts (Folha de estilo do componente)
┃ ┣ 📂configs (Grupo de variáveis de configuração destinado a uma lib ou parte do app)
┃ ┣ 📂contexts (Contexto)
┃ ┃ ┣ 📜AllProviders.tsx (Importação de todos os Contextos usado no app)
┃ ┃ ┣ 📜[Nome do Contexto]Context.spec.tsx (Implementação de controle de um contexto)
┃ ┃ ┗ 📜[Nome do Contexto]Context.tsx (Testes de um contexto)
┃ ┣ 📂hooks (Hooks compartilhado entre telas)
┃ ┃ ┣ 📜Use[Nome do Hook]Context.spec.tsx (Implementação de um hook)
┃ ┣ 📂routes (Gerenciamento de rotas)
┃ ┃ ┣ 📜AppNavigator.tsx (Gerenciamento principal de rotas do app - usúario autenticado)
┃ ┃ ┣ 📜AuthNavigator.tsx (Gerenciamento de rotas de um usúario não autenticado)
┃ ┃ ┗ 📜MockedNavigator.tsx (Gerenciamento de rotas para testes)
┃ ┣ 📂screens (Telas usado no App)
┃ ┃ ┣ 📂App (Telas principal do app - usúario autenticado)
┃ ┃ ┃ ┣ 📂[Nome do conjunto de tela]
┃ ┃ ┃ ┃ ┗ 📂[Nome da Tela]
┃ ┃ ┃ ┣ 📂[Nome da Tela]
┃ ┃ ┃ ┃ ┣ 📜index.tsx (Implementação da da tela)
┃ ┃ ┃ ┃ ┣ 📜index.spec.tsx (Teste da tela)
┃ ┃ ┃ ┃ ┣ 📜styles.ts (Folha de estilo da tela)
┃ ┃ ┃ ┃ ┣ 📂components (Componentes usado na tela apenas)
┃ ┃ ┃ ┃ ┃ ┣ 📂[Nome do componente]
┃ ┃ ┃ ┃ ┃ ┃ ┣ 📜index.tsx (Implementação do componente)
┃ ┃ ┃ ┃ ┃ ┃ ┣ 📜index.spec.tsx (Teste do componente)
┃ ┃ ┃ ┃ ┃ ┃ ┗ 📜styles.ts (Folha de estilo do componente)
┃ ┃ ┣ 📂Auth (Telas para o usúario não autenticado)
┃ ┃ ┃ ┗ 📂 [Nome da Tela]
┃ ┃ ┗ 📂SplashScreen (Tela de carregamento do app)
┃ ┣ 📂services (Serviços a serem consumido pelo app)
┃ ┃ ┣ 📜api.ts (Implementação dos métods da Web API)
┃ ┃ ┣ 📜[Nome do Serviço].ts (Implementação de um novo serviço)
┃ ┃ ┗ 📜[Nome do Serviço].spec.tsx (Realização do teste de um serviço)
┃ ┣ 📂tests (Utilitários para teste)
┃ ┃ ┣ 📂actions (Ações commum realizadas em testes)
┃ ┃ ┣ 📂mocks (Mocks para teste)
┃ ┃ ┃ ┣ 📜[Nome grupo de Mocks].ts (Implementação de mocks)
┃ ┃ ┃ ┣ 📜global.ts (Importação de todos os mocks usado globalmente)
┃ ┃ ┗ 📂responses (Mocks de request do Axios)
┃ ┃ ┃ ┗ 📜[Nome do método para request na API].ts (Implementação do mock)
┃ ┣ 📂theme (Implementação de estilo do app)
┃ ┃ ┣ 📜colors.dark.ts (Cores do app no modo dark)
┃ ┃ ┣ 📜colors.ts (Cores do app)
┃ ┃ ┣ 📜common.ts (Folha de estilo commun detro do app)
┃ ┃ ┣ 📜dimensions.ts (Dimensões commun dentro do app)
┃ ┃ ┗ 📜index.ts (Importação de todo o tema)
┃ ┣ 📂typings (Somente implementação de tipagem para o Typescript)
┃ ┣ 📂utils
┃ ┃ ┣ 📜[Nome do Utilitário].ts (Importação do utilitário)
┃ ┃ ┗ 📜[Nome do Utilitário].spec.tsx (Teste do utilitário)
┃ ┗ 📜App.tsx
┣ 📜.editorconfig (Configurações de editor de código)
┣ 📜.env.example (Exemplo de configurações de variável de ambiente)
┣ 📜.env.test (Configurações de variável de ambiente para teste)
┣ 📜.env (Configurações de variável de ambiente para o app)
┣ 📜.eslintrc.js(Configurações do ESlint)
┣ 📜.gitlab-ci.yml(Configurações pipeline do Gitlab)
┣ 📜.gitignore
┣ 📜.nvmrc (Configurações da versão do Node)
┣ 📜.prettierrc.js
┣ 📜.ruby-version (Configurações da versão do Roby)
┣ 📜.watchmanconfig
┣ 📜app.json
┣ 📜appcenter-config.json
┣ 📜appcenter-post-clone.sh
┣ 📜appcenter-pre-build.sh
┣ 📜babel.config.js (Configurações do babel)
┣ 📜Gemfile
┣ 📜index.js
┣ 📜jest.config.js (Configurações do Jest para testes)
┣ 📜jestSetupFile.js
┣ 📜metro.config.js
┣ 📜package.json (Configurações em geral do pacote)
┣ 📜react-native.config.js
┣ 📜tsconfig.json (Configurações do Typescript)
┗ 📜yarn.lock

Padrões de Estilo

O projeto usa ESlint, Prettier e EditorConfig, para controlar padrões de estilo. Abaixo estão algumas regras que ainda não podem ser aplicadas via uma dessas ferramentas.

  • Separar importação por contexto, sendo as primeiras importações do react e react native, depois do node module, e em seguida por grupo de pastar e por último importações com caminho relativo.

❌ Não fazer

import { alertSpy } from '@tests/actions/alertSpy';
import React from 'react';
import { mockedNavigate } from '@tests/mocks/rnNavigation';
import Home from './index';
import MockedNavigator from '@routes/MockedNavigator';
import { act, cleanup, render } from '@testing-library/react-native';

✅ Fazer isso

import React from 'react';

import { act, cleanup, render } from '@testing-library/react-native';

import { alertSpy } from '@tests/actions/alertSpy';
import { mockedNavigate } from '@tests/mocks/rnNavigation';

import MockedNavigator from '@routes/MockedNavigator';

import Home from './index';
  • Usar CamelCase em nomenclatura de variável. Permitido fuga do padrão quando trata de uma variável dentro de um corpo de um HTTP response/request.

❌ Não fazer

const firt_Name: string = 'João';
const LAST_NAME: string = 'Paulo';

✅ Fazer isso

const firtName: string = 'João';
const lastName: string = 'Paulo';
  • Informar o tipo no useState.

❌ Não fazer

const [isFocus, setIsFocus] = useState(false);
const [currentValue, setNewValue] = useState('');

✅ Fazer isso

const [isFocus, setIsFocus] = useState<boolean>(false);
const [currentValue, setNewValue] = useState<string>('');
  • Passando atributos no Styled. Atributos que utilizam as props, devem ter return em seu corpo pois a extensão do VSCode do styled buga sem esse padrão de estilo de código.

❌ Não fazer

export const ContainerTextInput = styled(TextInputComponent).attrs((props) => ({
  mode: props.mode || 'outlined',
  autoCapitalize: props.autoCapitalize || 'words',
  placeholderTextColor:
    props.placeholderTextColor || props.theme.colors.placeholderText,
  dense: true,
}))``;

✅ Fazer isso

export const ContainerTextInput = styled(TextInputComponent).attrs((props) => {
  return {
    mode: props.mode || 'outlined',
    autoCapitalize: props.autoCapitalize || 'words',
    placeholderTextColor:
      props.placeholderTextColor || props.theme.colors.placeholderText,
    dense: true,
  };
})``;

Testes

Para testes unitários está sendo utilizado biblioteca Jest e para escrever os testes é necessário criar arquivos .spec.ts/ .spec.tsx dentro do mesmo diretório em que se encontra o fragmento de código.

HTTP Request

Há alguns utilitários para facilitar a criação de testes, o primeiro deles é criar uma copiar mockado dos retornos da API localizado em src/tests/responses/, veja o exemplo de como criar um espelho de um request em src/tests/responses/exampleMethodName.ts.

Alert

Caso tenha um teste que envolva alerta, há um utilitário em src/tests/actions/alertSpy.ts, como ele você pode selecionar um botão em específico pelo nome:

import { alertSpy, onAlertActions } from '@tests/actions/alertSpy';

// ... //

const { pressAlertButton } = onAlertActions();

describe('Home Screen', () => {
  afterEach(() => {
    cleanup();
    alertSpy.mockClear();
  });

  // ... //

  it('should ...', async () => {
    // ... //

    await act(async () => {
      await waitFor(() => alertSpy);

      expect(alertSpy).toHaveBeenCalledTimes(1);
      expect(alertSpy).toHaveBeenLastCalledWith(
        'Falha!',
        'Não foi possível obter dados',
        expect.anything(),
        expect.anything(),
      );

      await pressAlertButton('Confirmar');
    });

    // ... //
  });
});

Render

Para carregamento correto dos render deve estar atento que ao realizar os testes de tela, deve ser usado o MockedNavigator:

import MockedNavigator from '@routes/MockedNavigator';

import NameScreen from './index';

// ... //

describe('Name Screen', () => {
  // ... //

  it('should render correctly', async () => {
    render(<MockedNavigator component={NameScreen} />);
    await act(async () => {});
  });

  // ... //
});

Agora caso precise apenas que faça o carregamento do tema em um componente pode ser usado o shadowTheme:

import { shadowTheme } from '@tests/actions/styledTheme';

import NameComponent from './index';

// ... //

describe('Name Component', () => {
  // ... //

  it('should render correctly', async () => {
    render(shadowTheme(<NameScreen placeholder="Test placeholder" />));
    await act(async () => {});
  });

  // ... //
});

Mocks

Os mocks a serem consumido no projeto podem ser criados em src/tests/mocks/ sendo separados em arquivos, de acordo com seu contexto ou biblioteca facilitando a manutenção. Os mocks que serão consumidos globalmente devem ser importados em src/tests/mocks/global.ts, os demais devem ser importando quando necessário no arquivo de spec do teste.

Dependências Recomendas

UI/Componentes

Autenticação

Notificação

Utilitário