Olá, estudante da Alura! Boas-vindas a mais um curso de React Native.
Audiodescrição: Pedro Mello é um homem branco, com cabelos e barba escuros. No nariz, utiliza um piercing no septo e outro na narina direita. No corpo, veste uma camiseta preta. Ao fundo um ambiente branco iluminado em tons de rosa e azul, com quadros à esquerda e guitarras e uma estante cheia de figuras de ação à direita.
Este curso está repleto de conteúdos interessantes. Vamos explorar o Desbrava App, um aplicativo voltado para registros de aventuras. Nossa missão será cadastrar um formulário de novas aventuras, permitindo que a pessoa usuária adicione uma foto através da câmera nativa do celular.
Vamos desenvolver tudo do zero. Receberemos o código, mas visitaremos toda a estrutura, desde a adição das permissões nativas, o desenvolvimento do formulário, até a captura de uma foto utilizando os emuladores. Faremos isso em conjunto, desde a instalação das dependências até a codificação e verificação do funcionamento completo.
Teremos tanto o simulador do iOS quanto do Android, pois estamos utilizando uma plataforma macOS que possibilita ter ambas as plataformas de emuladores. A tela em ambos é a mesma:
Clicando em "Adicionar aventura!", temos o formulário de aventuras e acesso à câmera.
No Android, ao clicar no campo "Adicionar uma imagem", acessamos uma tela com a simulação da câmera do dispositivo para registrar a foto e exibir; no iOS, não temos essa possibilidade pelo simulador.
Vamos fazer isso do zero. Portanto, este curso pode requerer conhecimento prévio sobre como funciona o React e o React Native, incluindo aspectos como ScrollView e a necessidade de colocar o texto em volta de um componente de textos. Essas informações serão abordadas de forma superficial, focando na parte nativa e na configuração mais avançada.
Também é necessário conhecer o Expo e o TypeScript, utilizados neste curso para realizar as tipagens e tornar nosso código mais robusto durante a codificação.
Se você não tiver conhecimento nesses assuntos, não se preocupe! Temos esses conteúdos disponíveis na Alura para consulta, caso prefira assisti-los antes de mergulhar neste mundo do Desbrava App.
Vamos começar sem muita demora, pois queremos iniciar e codificar este projeto. Vejo vocês na sequência. Vamos lá!
Vamos explorar o aplicativo que a Desbrava App nos forneceu e identificar os pontos que precisamos trabalhar e implementar.
Estamos com o editor de texto aberto no projeto do Desbrava App. Acessando oa aba do explorador de arquivos na lateral esquerda, abriremos o package.json
na raiz do projeto.
Em seu interior, perceberemos que ele utiliza o Expo, pela forma como executa os scripts. Nas dependências, já estão implementadas funcionalidades de navegação, o Expo, o Gesture Handler e o React Native Paper. Este último traz componentes do Material UI convertidos para o React Native, já que o Material UI é voltado para web.
Explorando os arquivos, encontramos a pasta "assets" com os PNG do favicon e da logo do projeto. Dentro de "componentes", já temos o AppHeader implementado junto com a navegação. Observamos também as pastas "android" e "ios", indicando que o projeto utiliza a arquitetura Expo Bare Workflow, que consiste em ter acesso aos Expo Modules e às pastas nativas de ambas as plataformas.
Antes de começar, vale ressaltar que estamos utilizando um macOS, o que nos permite rodar emuladores de iOS e Android. Quem utilizar Linux ou Windows provavelmente terá acesso apenas ao Android, mas isso não impede o funcionamento do código em ambas as plataformas.
Acessando o terminal integrado do editor de texto com o atalho "Ctrl + '", executaremos o comando abaixo para rodar no emulador do iOS:
npm run ios
Abriremos outra instância do terminal, clicando em "Split terminal" no canto direito, para executar o comando abaixo que roda no Android:
npm run android
Fazemos isso separadamente porque esse comando realiza um build do zero do projeto (essencial na primeira execução) ou após a instalação de novas bibliotecas. No iOS, o processo envolve a execução do pod, enquanto no Android, refaz os links.
Com a aplicação rodando no simulador do iOS, a tela "Minhas Aventuras" exibe um botão para adicionar aventura, que por enquanto não realiza nenhuma ação. O cabeçalho contém o título da tela e um botão de lupa, também sem funcionalidade no momento.
O bottom tab navigator (navegador de abas inferiores) permite navegar entre as telas "Lembretes" e "Aventuras". Em "Lembretes", não há a lupa de pesquisa e há um botão de adicionar lembrete sem a funcionalidade implementada.
No Android, notamos algumas diferenças de design: o título do cabeçalho é alinhado à esquerda por padrão, enquanto no iOS ele aparece centralizado. Além disso, no Android, o botão flutuante na parte inferior da tela mantém a cor preta, enquanto no iOS, ele se integra à cor da bottom tab.
Nosso objetivo agora é criar um formulário para adicionar novas aventuras, permitindo edição posterior e a possibilidade de anexar imagens. Esse recurso será útil para registrar momentos, como trilhas ou visitas a cachoeiras.
No editor de texto, fecharemos os arquivos abertos. No explorador lateral, dentro do caminho de pastas "src > screens", criaremos a pasta "AdventureForm" e o arquivo index.tsx
em seu interior.
Acessando esse arquivo, começaremos com a estrutura básica abaixo, importando View
, Text
e React
. Alteraremos o nome da constante para AdventureForm
e o Text
para "Adicionar aventura". Por fim, salvaremos o arquivo.
index.tsx
:
import { View, Text } from 'react-native';
import React from 'react';
const AdventureForm = () => {
return (
<View>
<Text>Adicionar aventura</Text>
</View>
);
};
export default AdventureForm;
Na sequência, cadastraremos essa tela na navegação do projeto. Até lá!
Discutiremos a navegação em nossa aplicação. Vamos acessar o arquivo src/navigation/index.tsx
para analisar como está funcionando a navegação.
Observamos que já existe uma bottom tab criada, que pode ser visualizada no bloco export default function BottomTabNavigator()
, que se estende por 74 linhas. Essa bottom tab é exibida na parte inferior do aplicativo, onde temos as seções "Aventuras" e "Lembretes".
index.tsx
de "navigation":
export default function BottomTabNavigator() {
{/* Código omitido */}
}
Abaixo desse trecho, temos a stack, que é o nosso AppRootNavigator
, definindo que a tela principal é a tela de aventuras. O componente utilizado é o BottomTabNavigator
, ou seja, a tela principal da stack é o nosso BottomTabNavigator
.
const Stack = createStackNavigator();
export function AppRootNavigator() {
return (
<Stack.Navigator id={undefined} screenOptions={{ headerShown: false }}>
<Stack.Screen name='Adventures' component={BottomTabNavigator} />
</Stack.Navigator>
);
}
A stack funciona de forma empilhada. Por exemplo, podemos imaginar duas paletas, onde uma é colocada sobre a outra. A rota inicial, representada pela paleta de baixo, é como o BottomTabNavigator
. Se quisermos acessar outra rota a partir do BottomTabNavigator
, seria como a paleta de cima.
Vamos iniciar a tipagem da tela AdventureForm
. No início do arquivo, temos o bloco RootStackParamList
, que identifica os parâmetros que podemos passar para nossa rota. Atualmente, está definido como undefined
, pois não estamos passando nada específico para as telas de aventuras ou lembretes.
No entanto, para a tela AdventureForm
, podemos passar um ID ou algo que facilite a identificação, especialmente quando o modo de edição estiver habilitado. Isso pode ser feito pelo lado do pageContext
. Por enquanto, entre as chaves do RootStackParamList
, adicionaremos AdventureForm: undefined
.
export type RootStackParamList = {
Adventures: undefined;
Reminders: undefined;
AdventureForm: undefined;
};
A partir desse momento, temos a rota AdventureForm
dentro da nossa navegação. Ainda não haverá redirecionamento, pois não criamos o redirecionamento dentro da stack, mas já temos uma identificação.
Para que o redirecionamento ocorra, acessaremos o return
da função AppRootNavigator()
, no final do arquivo. Em seu interior, abaixo da Stack.Screen
Adventures
, adicionaremos outra Stack.Screen
com o nome AdventureForm
, e o componente a ser renderizado será o AdventureForm
.
export default function AppRootNavigator() {
return (
<Stack.Navigator id={undefined} screenOptions={{ headerShown: false }}>
<Stack.Screen name='Adventures' component={BottomTabNavigator} />
<Stack.Screen name='AdventureForm' component={AdventureForm} />
</Stack.Navigator>
);
}
Pode parecer confuso ver um Navigator
dentro de outro. No momento da gravação deste vídeo, existem discussões sobre versões mais recentes do React Native com o Expo adotarem uma navegação semelhante ao Next.js, baseada em arquivos e estrutura de pastas. No entanto, neste projeto específico, não utilizamos essa arquitetura de navegação por pastas, comum em Next.js e outros frameworks voltados para React.
No React Native com o Expo que estamos utilizando, precisamos usar o React Navigation para lidar com as rotas.
app.tsx
Vamos remover o export default
do BottomTabNavigator
, por volta da linha 24, e colocar o export default
no nosso AppRootNavigator
.
function BottomTabNavigator() {
{/* Código omitido */}
}
export default function AppRootNavigator() {
{/* Código omitido */}
}
A alteração na parte de navegação é essa. Precisamos apenas alterar o App.tsx
.
No interior desse arquivo, o MyComponent
está utilizando o export default
do Navigation
, que era do nosso BottomTabNavigator
. Na raiz do nosso projeto, em vez de MyComponent
, vamos importar AppRootNavigator
. Na linha que utiliza o MyComponent
, faremos essa troca para melhorar a organização do código.
import AppRootNavigator from './src/navigation';
export default function App() {
return (
<NavigationContainer theme={DarkTheme}>
<StatusBar style='light' />
<AppRootNavigator />
</NavigationContainer>
);
}
Como esse código veio da Desbrava para que pudéssemos fazer as alterações, estamos aprimorando dentro das possibilidades para o nosso projeto.
Para testar essa navegação, vamos acessar as pastas "screens > Adventures" e o arquivo index.tsx
. Vamos importar o hook de navegação chamado useNavigation
. Passaremos a tipagem do RootStackNavigationProp
para garantir que a navegação ocorra apenas para rotas existentes.
Em seguida, faremos a alteração no botão para testar se resolvemos o problema de navegação. Atualmente, ao abrir ambos os simuladores, a navegação não ocorre, mesmo já tendo adicionado a tela na stack.
Na primeira linha dentro das chaves do bloco const Adventures = () => {}
, declararemos const navigation = useNavigation
. Vamos adicionar os sinais <>
para fazer a tipagem RootStackNavigationProp
.
index.tsx
de "Adventures":
const Adventures = () => {
const navigation = useNavigation<RootStackNavigationProp>();
{/* Código omitido */}
}
Faremos a importação do useNavigation
de @react-navigation/native
e a importação da tipagem da NavigationProps
do nosso RootStack
.
import { useNavigation } from '@react-navigation/native';
import { RootStackNavigationProp } from '../../navigation';
No bloco const Adventures = () => {}
vamos alterar o onPress
do Button
, substituindo o par de chaves da arrow function pelo navigation.navigate()
. Clicando entre seus parênteses, o editor de texto já identifica, através da tipagem, que as rotas disponíveis para navegação na stack são AdventureForm
, Adventures
e Reminders
. Após clicar em AdventureForm
, salvaremos a tela.
<Button
mode='contained'
onPress={() => navigation.navigate('AdventureForm')}
style={{ marginTop: 16, backgroundColor: colors.primary }}
textColor={colors.black}
>
Adicionar aventura!
</Button>
Vamos conferir nos emuladores, começando pelo Android. Ao clicar em "Adicionar aventura!", a navegação ocorre. No iOS, ocorre o mesmo.
Para visualizar o conteúdo em tela, já que a fonte está na cor preta e o fundo também é preto, vamos adicionar um estilo. Acessando o arquivo index.tsx
da pasta "AdventureForm", definiremos a cor do Text
como colors.surface
, o que já dará uma diferença.
index.tsx
de "AdventureForm":
<View>
<Text style={{ color: colors.onSurface }}>Adicionar aventura</Text>
</View>
Faremos a importação pelos nossos tokens de cor.
import { colors } from '../../styles/colors';
No simulador, observaremos que o "Adicionar aventura!" está no topo da aplicação, sendo difícil de ver. Para resolver isso, adicionaremos um AppHeader
da nossa aplicação acima da View
do texto, passando a propriedade title
como "Adicionar aventura" e um showBackButton
.
Por fim, adicionaremos um fragment envolvendo e aninhando todos esses componentes.
<>
<AppHeader title='Adicionar aventura' showBackButton />
<View>
<Text style={{ color: colors.onSurface }}>Adicionar aventura</Text>
</View>
</>
Voltando aos emuladores, tudo está funcionando corretamente. O texto "Adicionar aventura" voltará a ser exibido no local correto.
A navegação já está funcionando para ir e voltar entre as telas. A seguir, discutiremos as diferenças entre os componentes de header e criaremos os componentes de botão e outros elementos.
O curso React Native: integrando câmera nativa para capturar fotos possui 126 minutos de vídeos, em um total de 47 atividades. Gostou? Conheça nossos outros cursos de em Mobile, ou leia nossos artigos de Mobile.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.