Noções Básicas de React Native
10 exemplos para você começar com os Fundamentos do React Native - 7 básicos e 3 intermediários.
Busque em todas as páginas da documentação
10 exemplos para você começar com os Fundamentos do React Native - 7 básicos e 3 intermediários.
Aplicativos React Native precisam de um runtime nativo. O caminho mais rápido é Expo, que fornece um Metro bundler pré-configurado, cliente de desenvolvimento e módulos nativos comuns.
npx create-expo-app@latest MyApp
cd MyApp
npx expo startEscaneie o código QR com o Expo Go em um dispositivo físico, ou pressione i / a no terminal para abrir o Simulador iOS ou o emulador Android. Edite App.tsx - cada exemplo abaixo pode substituir esse arquivo para ser executado imediatamente.
Ferramentas: Estes exemplos visam o Expo SDK 57, React Native 0.86 e React 19.2.3. TypeScript (
.tsx) é usado em todo o material; projetos Expo o incluem por padrão.
Os dois primitivos dos quais cada tela React Native é construída - View para contêineres de layout e Text para qualquer coisa que o usuário leia.
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.title}>Olá, React Native!</Text>
<Text style={styles.subtitle}>Construído com View e Text.</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center" },
title: { fontSize: 24, fontWeight: "bold" },
subtitle: { fontSize: 16, color: "#666", marginTop: 8 },
});<div> ou <p> - View mapeia para um contêiner nativo e Text mapeia para um nó de texto nativo<Text> - colocar uma string bruta dentro de View gera um erro em tempo de execuçãoflex: 1 no contêiner faz com que ele preencha toda a tela, que é o padrão de layout raizfontSize, não font-size)Relacionado: Views, Text & Core Components - regras de aninhamento,
TextInpute peculiaridades de renderização de plataforma
Use StyleSheet.create para definir objetos de estilo reutilizáveis e validados em vez de literais inline.
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.card}>
<Text style={styles.heading}>StyleSheet.create</Text>
<Text style={styles.body}>
Estilos são definidos uma vez e referenciados por chave.
</Text>
</View>
);
}
const styles = StyleSheet.create({
card: {
margin: 16,
padding: 20,
backgroundColor: "#f0f4ff",
borderRadius: 12,
borderWidth: 1,
borderColor: "#c7d2fe",
},
heading: { fontSize: 18, fontWeight: "600", marginBottom: 8 },
body: { fontSize: 14, lineHeight: 20, color: "#374151" },
});StyleSheet.create valida nomes de propriedades em tempo de desenvolvimento e envia um ID de estilo para a camada nativa em vez de um objeto completo a cada renderizaçãostyle={{ margin: 16 }}) funcionam para casos únicos, mas StyleSheet é preferível para qualquer coisa reutilizada ou compostastyle={[styles.base, isActive && styles.active]} - entradas posteriores substituem as anterioresem/remRelacionado: Views, Text & Core Components - como os estilos se anexam às views nativas
React Native usa Flexbox para todo o layout. A flexDirection padrão é column, não row como muitos layouts da web assumem.
import { View, Text, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.screen}>
<View style={styles.header}>
<Text style={styles.headerText}>Cabeçalho</Text>
</View>
<View style={styles.row}>
<View style={[styles.box, styles.boxA]}>
<Text>A</Text>
</View>
<View style={[styles.box, styles.boxB]}>
<Text>B</Text>
</View>
</View>
<View style={styles.footer}>
<Text style={styles.footerText}>Rodapé</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, padding: 16 },
header: { padding: 12, backgroundColor: "#dbeafe", borderRadius: 8 },
headerText: { fontWeight: "600" },
row: { flex: 1, flexDirection: "row", gap: 12, marginVertical: 16 },
box: { flex: 1, justifyContent: "center", alignItems: "center", borderRadius: 8 },
boxA: { backgroundColor: "#bbf7d0" },
boxB: { backgroundColor: "#fde68a" },
footer: { padding: 12, backgroundColor: "#f3f4f6", borderRadius: 8 },
footerText: { textAlign: "center", color: "#6b7280" },
});flex: 1 em views irmãs faz com que elas compartilhem o espaço restante igualmente ao longo do eixo principal do paiflexDirection: "row" muda o eixo principal para horizontal - essencial para layouts lado a ladojustifyContent alinha os filhos ao longo do eixo principal; alignItems alinha ao longo do eixo transversalgap (RN 0.71+) adiciona espaçamento entre os filhos flex sem hacks de margemRelacionado: Dimensões & Layout Responsivo - breakpoints, tablets e grades adaptativas
Pressable é o primitivo de toque moderno - ele expõe o estado de pressionamento para que você possa estilizar o feedback sem um wrapper de opacidade separado.
import { useState } from "react";
import { View, Text, Pressable, StyleSheet } from "react-native";
export default function App() {
const [lastPress, setLastPress] = useState("Nenhum toque ainda");
return (
<View style={styles.container}>
<Pressable
onPress={() => setLastPress(new Date().toLocaleTimeString())}
style={({ pressed }) => [
styles.button,
pressed && styles.buttonPressed,
]}
>
<Text style={styles.buttonText}>Toque aqui</Text>
</Pressable>
<Text style={styles.status}>{lastPress}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center", gap: 16 },
button: {
backgroundColor: "#2563eb",
paddingHorizontal: 24,
paddingVertical: 12,
borderRadius: 8,
},
buttonPressed: { backgroundColor: "#1d4ed8", transform: [{ scale: 0.97 }] },
buttonText: { color: "#fff", fontWeight: "600", fontSize: 16 },
status: { color: "#6b7280" },
});style aceita uma função ({ pressed }) => [...] para que o estilo do estado pressionado permaneça declarativoonPress é acionado em um toque concluído; use onPressIn / onPressOut para cenários de pressionar e segurar ou arrastarhitSlop para ampliar o alvo de toque sem alterar o tamanho visual - crítico para acessibilidade em ícones pequenosPressable substitui TouchableOpacity e TouchableHighlight em código novoRelacionado: Manipulação de Eventos & Touchables -
hitSlop, toque longo e camadas de gestos
useState funciona da mesma forma que no React para web - uma mudança de estado agenda uma re-renderização da árvore de componentes.
import { useState } from "react";
import { View, Text, Pressable, StyleSheet } from "react-native";
export default function App() {
const [count, setCount] = useState(0);
return (
<View style={styles.container}>
<Text style={styles.count}>{count}</Text>
<View style={styles.row}>
<Pressable style={styles.button} onPress={() => setCount((c) => c - 1)}>
<Text style={styles.buttonText}>−</Text>
</Pressable>
<Pressable style={styles.button} onPress={() => setCount((c) => c + 1)}>
<Text style={styles.buttonText}>+</Text>
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center", gap: 24 },
count: { fontSize: 48, fontWeight: "bold" },
row: { flexDirection: "row", gap: 12 },
button: {
backgroundColor: "#2563eb",
width: 56,
height: 56,
borderRadius: 28,
justifyContent: "center",
alignItems: "center",
},
buttonText: { color: "#fff", fontSize: 24, fontWeight: "600" },
});count imediatamente após setCount ainda retorna o valor antigosetCount((c) => c + 1) quando o novo valor depender do anterioruseState dispara uma re-renderização deste componente e seus filhos - mantenha o estado o mais local possívelRelacionado: Props, State & Re-renders no Mobile - como as atualizações cruzam a fronteira JS/nativa
Exiba ativos locais empacotados com require() ou imagens remotas com um objeto de origem { uri }.
import { View, Image, Text, StyleSheet } from "react-native";
const REMOTE_URI =
"https://reactnative.dev/img/tiny_logo.png";
export default function App() {
return (
<View style={styles.container}>
<Image source={require("./assets/icon.png")} style={styles.local} />
<Image source={{ uri: REMOTE_URI }} style={styles.remote} />
<Text style={styles.caption}>Ativo local (topo) e URI remota (inferior)</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center", gap: 16 },
local: { width: 64, height: 64, borderRadius: 12 },
remote: { width: 64, height: 64 },
caption: { fontSize: 13, color: "#6b7280", textAlign: "center", paddingHorizontal: 24 },
});require("./assets/icon.png") é resolvido em tempo de compilação - o bundler inclui o arquivo e seleciona a densidade correta (@2x, @3x)width e height explícitos (ou aspectRatio) - RN não pode inferir dimensões apenas de uma URLresizeMode (cover, contain, stretch) para controlar como a imagem preenche seus limitesexpo-image - abordado no guia dedicado de imagensRelacionado: Imagens & Ativos - buckets de densidade,
expo-assete estratégias de cache
Envolva o conteúdo da tela em SafeAreaView para que ele limpe entalhes, barras de status e indicadores de início.
import { Text, StyleSheet } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
export default function App() {
return (
<SafeAreaView style={styles.safe}>
<Text style={styles.title}>Layout de Área Segura</Text>
<Text style={styles.body}>
O conteúdo permanece abaixo da barra de status e acima do indicador de início.
</Text>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safe: { flex: 1, padding: 20, backgroundColor: "#fff" },
title: { fontSize: 22, fontWeight: "bold", marginBottom: 8 },
body: { fontSize: 15, lineHeight: 22, color: "#4b5563" },
});react-native-safe-area-context, não de react-native - o SafeAreaView embutido é apenas para iOS e obsoleto para novos aplicativosreact-native-safe-area-context por padrão; envolva sua raiz em SafeAreaProvider (o template do Expo faz isso)useSafeAreaInsets() quando precisar de controle por borda - por exemplo, um cabeçalho de tela cheia com apenas preenchimento superiorStatusBar de expo-status-bar para corresponder ao estilo da barra de status com sua cor de fundoRelacionado: Views, Text & Core Components - primitivos de layout em nível de tela
Use Platform.OS para ramificações simples e Platform.select para valores de estilo específicos da plataforma.
import { View, Text, Platform, StyleSheet } from "react-native";
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.label}>
Executando em {Platform.OS === "ios" ? "iOS" : "Android"}
</Text>
<View style={styles.card}>
<Text style={styles.cardText}>
{Platform.OS === "ios"
? "Fonte do sistema San Francisco"
: "Fonte do sistema Roboto"}
</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center", gap: 16 },
label: { fontSize: 16, color: "#6b7280" },
card: {
padding: 20,
borderRadius: 12,
backgroundColor: "#f9fafb",
...Platform.select({
ios: {
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
android: { elevation: 4 },
}),
},
cardText: { fontSize: 15 },
});Platform.OS retorna "ios", "android", "web" ou "windows" - use-o para pequenas ramificações condicionaisPlatform.select({ ios: {...}, android: {...} }) retorna o valor correspondente e se espalha de forma limpa em objetos StyleSheetshadow*; Android usa elevation - Platform.select é a maneira idiomática de lidar com essa divisão.ios.tsx / .android.tsx em vez de condicionais inlineRelacionado: Código Específico da Plataforma - extensões de arquivo, módulos nativos e
Platform.Version
Reaja a mudanças de tamanho de tela - rotação, dobráveis e tablets - com o hook useWindowDimensions.
import { View, Text, useWindowDimensions, StyleSheet } from "react-native";
export default function App() {
const { width } = useWindowDimensions();
const isTablet = width >= 768;
const columns = isTablet ? 3 : 2;
const gap = isTablet ? 16 : 8;
const horizontalPadding = 32;
const tileSize =
(width - horizontalPadding - gap * (columns - 1)) / columns;
return (
<View style={styles.container}>
<Text style={styles.heading}>
Layout de {columns} colunas ({Math.round(width)}px de largura)
</Text>
<View style={[styles.grid, { gap }]}>
{Array.from({ length: 6 }, (_, i) => (
<View key={i} style={[styles.tile, { width: tileSize, height: tileSize }]}>
<Text>Item {i + 1}</Text>
</View>
))}
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16 },
heading: { fontSize: 16, fontWeight: "600", marginBottom: 16 },
grid: { flexDirection: "row", flexWrap: "wrap" },
tile: {
backgroundColor: "#e0e7ff",
borderRadius: 8,
justifyContent: "center",
alignItems: "center",
},
});useWindowDimensions re-renderiza na rotação e redimensionamento da janela, ao contrário do snapshot estático Dimensions.get("window")768 para tablet) como constantes nomeadas compartilhadas em todo o aplicativowidth menos padding e gaps - dimensões numéricas evitam surpresas de layout percentualflexBasis e flexWrap em vez de posicionamento absolutoRelacionado: Dimensões & Layout Responsivo - API
Dimensions, hooks de orientação e suporte a dobráveis
Combine View, Text, Image, Pressable, StyleSheet e Platform.select em um cartão reutilizável e interativo.
import { useState } from "react";
import {
View,
Text,
Image,
Pressable,
Platform,
StyleSheet,
} from "react-native";
const AVATAR_URI = "https://reactnative.dev/img/tiny_logo.png";
export default function App() {
const [following, setFollowing] = useState(false);
return (
<View style={styles.screen}>
<View style={styles.card}>
<Image source={{ uri: AVATAR_URI }} style={styles.avatar} />
<Text style={styles.name}>Alex Rivera</Text>
<Text style={styles.bio}>Desenvolvedor React Native · 42 projetos</Text>
<Pressable
onPress={() => setFollowing((f) => !f)}
style={({ pressed }) => [
styles.followButton,
following && styles.following,
pressed && styles.followPressed,
]}
>
<Text
style={[
styles.followText,
following && styles.followingText,
]}
>
{following ? "Seguindo" : "Seguir"}
</Text>
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1, justifyContent: "center", padding: 24, backgroundColor: "#f3f4f6" },
card: {
backgroundColor: "#fff",
borderRadius: 16,
padding: 24,
alignItems: "center",
...Platform.select({
ios: {
shadowColor: "#000",
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.12,
shadowRadius: 8,
},
android: { elevation: 6 },
}),
},
avatar: { width: 80, height: 80, borderRadius: 40, marginBottom: 12 },
name: { fontSize: 20, fontWeight: "bold" },
bio: { fontSize: 14, color: "#6b7280", marginTop: 4, marginBottom: 16 },
followButton: {
backgroundColor: "#2563eb",
paddingHorizontal: 32,
paddingVertical: 10,
borderRadius: 20,
},
following: { backgroundColor: "#e5e7eb" },
followPressed: { opacity: 0.85 },
followText: { color: "#fff", fontWeight: "600" },
followingText: { color: "#374151" },
});View), conteúdo (Text, Image), interação (Pressable), e estilização (StyleSheet)useState e derive o rótulo e o estilo do botão a partir do mesmo booleano - uma única fonte de verdadename, bio, avatarUri) como o próximo passo em direção a uma biblioteca de componentesRelacionado: Props, State & Re-renders no Mobile - extraindo componentes reutilizáveis | Melhores Práticas - padrões para UI mobile pronta para produção
Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026