Fundamentos React Native
React Native + Expo · notas de aula

A anatomia de uma tela React Native

Todo app nasce da combinação de poucas peças: caixas que organizam, texto que informa, botões que reagem e um pouco de memória pra lembrar o que o usuário fez. Este é o mapa dessas peças e dos comandos de terminal que colocam tudo isso rodando no seu celular.

Nesta página

Antes de tudo

O Expo (a ferramenta que usamos para criar e rodar o app) precisa do Node.js instalado. É ele quem roda o servidor local e todo o ferramental por trás das câmeras. Antes de criar qualquer projeto, confirme que os dois comandos abaixo respondem com um número de versão, não com erro.

Terminal
> node --version
v20.11.1
Terminal
> npm --version
10.2.4

Criando e rodando o projeto

1
Terminal
> npx create-expo-app NomeDoSeuApp --template blank-typescript

Baixa da internet toda a estrutura do Expo e cria a pasta do app. O --template blank-typescript garante que o projeto venha limpo, sem exemplos, já configurado para TypeScript.

2
Terminal
> cd NomeDoSeuApp

O terminal não entra na pasta sozinho. Sem esse passo, os comandos seguintes rodam no lugar errado.

3
Terminal
> npx expo install react-dom react-native-web
> npx expo install react-native-safe-area-context

O template em branco não vem com suporte à Web nem com a biblioteca de área segura, por isso instalamos os dois. Usar expo install (em vez de npm install) garante versões compatíveis com a sua versão do Expo.

4
Terminal
> npx expo start
› Metro waiting on exp://192.168.0.12:8081
› Scan the QR code above with Expo Go

O comando do dia a dia: liga o servidor local e gera o QR Code para abrir o app no celular.

wabre o app numa aba do navegador (Web)
rrecarrega o app do zero
climpa o terminal
Ctrl+Cdesliga o servidor

01 · Componentes visuais

A estrutura da tela. Antes de qualquer coisa reagir a um toque, alguém precisa organizar as caixas, colocar o texto dentro delas e definir onde a imagem entra. É o "esqueleto" de todo componente que você vai construir.

O padrão que você vai repetir bastante

Toda tela começa envolvendo o conteúdo num SafeAreaProvider e, dentro dele, num SafeAreaView. É esse par que garante que nada fique escondido atrás da câmera ou da barra de gestos do celular.

App.tsx
<SafeAreaProvider>
<SafeAreaView style={styles.container}>
<Text>Esse texto está protegido!</Text>
</SafeAreaView>
</SafeAreaProvider>
conteúdo do
SafeAreaView

Zonas de risco: câmera/notch em cima, barra de gestos embaixo. Um View comum deixaria conteúdo nascer aqui, escondido ou cortado.

Área segura: o SafeAreaView calcula o respiro certo em cada aparelho, sem número mágico, sem margem fixa que quebra num iPhone e sobra noutro.

<View/>

A caixa universal de layout, equivalente à <div> do HTML. Organiza os filhos em Flexbox (coluna, por padrão).

Use quando precisar agrupar, alinhar ou espaçar qualquer coisa na tela.

<View style={styles.caixa}> <Text>oi</Text> </View>

<SafeAreaView/>

A view inteligente: respeita as bordas perigosas do aparelho, como câmera, status bar e barra de gestos.

Use quando for a raiz visível de qualquer tela do app.

<Text/>

O único componente que aceita palavras soltas. Toda letra do app precisa estar dentro de um Text.

Use quando mostrar qualquer palavra, número ou frase.

<Text>Olá, mundo!</Text>

<Image/>

Mostra fotos e ícones: locais (require()) ou remotos (uri). Precisa de largura/altura definidas.

Use quando exibir uma foto, ícone ou ilustração.

<Image // de onde vem a imagem source={{ uri: 'https://...' }} // tamanho é obrigatório style={{ width: 64, height: 64 }} />

<ImageBackground/>

Um Image que aceita filhos por cima, ideal para uma foto de fundo com texto ou formulário na frente.

Use quando precisar de conteúdo sobreposto a uma imagem.

<ImageBackground source={require('./fundo.png')} style={styles.fundo}> <Text>Bem-vindo</Text> </ImageBackground>

<StyleSheet/>

A nossa folha de estilos, o "CSS" do React Native. StyleSheet.create({ '{' }...{ '}' }) organiza os estilos em objeto JS.

Use quando estilizar qualquer componente (sem unidade: número puro = dp).

const styles = StyleSheet.create({ caixa: { padding: 16, borderRadius: 8 } })

02 · Interatividade

Ações do usuário. Uma tela bonita e parada não é um app: é aqui que o toque, a digitação e o liga/desliga entram em cena. Mexa nos exemplos abaixo, eles respondem de verdade.

Repara que várias funções aqui começam com set, tipo setNome e setAtivo. Isso não é acaso: são "atualizadores de estado", a peça que faz a tela lembrar do que o usuário fez. O porquê disso mora lá na frente, em Lógica & estado.

Button × TouchableOpacity
Button: 0 toques · TouchableOpacity: 0 toques
TextInput
A tela mostra: (vazio)
Switch
desligado
value={ false }

<Button/>

O botão padrão do sistema. O visual muda entre iOS e Android. Recebe só title, onPress e color.

Limite quase não dá pra customizar o estilo.

<Button title="Entrar" onPress={() => login()} />

<TouchableOpacity/>

Torna qualquer coisa tocável e reduz a opacidade ao pressionar. É o feedback que você acabou de sentir nos botões acima.

Use quando quiser 100% de controle do visual do botão.

// setCurtiu atualiza o estado <TouchableOpacity onPress={() => setCurtiu(true)}> <Text>Curtir</Text> </TouchableOpacity>

<TextInput/>

Abre o teclado e captura o que o usuário digita. Controlado com value + onChangeText.

Use quando precisar de nome, e-mail, busca, senha…

<TextInput // o que está escrito agora value={nome} // setNome guarda o texto digitado onChangeText={setNome} // dica em cinza, some ao digitar placeholder="Seu nome" />

<Switch/>

O toggle nativo de ligar/desligar. Controlado com value (boolean) + onValueChange.

Use quando a opção for binária: sim/não, ativo/inativo.

<Switch // true ou false: estado atual value={ativo} // setAtivo atualiza o estado onValueChange={setAtivo} />

03 · Listas e rolagem

Para conteúdo grande demais pra caber numa tela. A diferença entre os três é o que cada um mantém montado na memória enquanto você rola.

ScrollView

Renderiza todos os filhos de uma vez, mesmo fora da tela. Ótimo pra pouco conteúdo, pesado demais pra listas grandes.

<ScrollView> <Text>Item 1</Text> <Text>Item 2</Text> </ScrollView>

FlatList

Lista virtualizada: só monta o que aparece na tela (+ uma folga). Padrão para qualquer lista média ou grande.

<FlatList // o array com os itens data={produtos} // como desenhar 1 item renderItem={...} />

SectionList

Como a FlatList, mas agrupada por categorias com cabeçalho, tipo a agenda do celular separada em A, B, C…

<SectionList // os grupos: [{ title, data }] sections={grupos} // como desenhar 1 item renderItem={...} // como desenhar o título do grupo renderSectionHeader={...} />

ScrollView · como isso vira código

A mais direta das três: tudo que você coloca dentro dela vira filho normal, sem prop de dados nem função de desenho. Boa pra conteúdo curto e fixo, tipo um formulário longo. Evite se a lista pode crescer pra centenas de itens.

App.tsx
<ScrollView>
<Text>Item 1</Text>
<Text>Item 2</Text>
<Text>Item 3</Text>
</ScrollView>

FlatList · como isso vira código

A FlatList não recebe filhos prontos: você entrega os dados em data e uma função em renderItem que diz como desenhar cada linha. O keyExtractor dá um id único pra cada item, é assim que o React sabe o que redesenhar quando a lista muda.

App.tsx
<FlatList
data={produtos} // o array de itens
keyExtractor={(item) => item.id} // id único de cada item
renderItem={({ item }) => ( // como desenhar 1 item
<Text>{item.nome}</Text>
)}
/>

SectionList · como isso vira código

Espera os dados já agrupados em sections: uma lista de grupos, cada um com um title e um data (os itens daquele grupo). O renderItem desenha cada item e o renderSectionHeader desenha o título do grupo.

App.tsx
const grupos = [
{ title: 'A', data: ['Ana', 'Aline'] },
{ title: 'B', data: ['Bianca'] },
]
<SectionList
sections={grupos}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => (
<Text>{section.title}</Text>
)}
/>

FlatList · role a lista, o "viewport" é o que fica montado

visíveis agora: 0 de 24 itens

SectionList · cabeçalho fixo por grupo

04 · Lógica e estado

O cérebro do app. useState é o comando do React que guarda a memória da tela: o que o usuário digitou, se o switch está ligado, quantas vezes um botão foi tocado. Quando essa memória muda, a tela é redesenhada sozinha.

const [n, setN] = useState(0)
usuário toca no botão
setN(n + 1)
tela re-renderiza com o novo valor
useState ao vivo
0
const [count, setCount] = useState(0)
<TouchableOpacity onPress={() => setCount(count + 1)}>