🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

Tutorial React Native 2026: Expo, navegação e implantação da App Store

⏱️5 min read  ·  889 words

React Native em 2026 com a nova arquitetura (JSI + Fabric), Expo SDK 52 e suporte para React 19 torna a construção de aplicativos móveis de produção mais rápida do que nunca. Se você já conhece o React, o React Native permite criar aplicativos iOS e Android com 85-90% de código compartilhado. Este tutorial cobre o essencial.

Configurar

# Using Expo (recommended for new projects)
npx create-expo-app@latest MyApp
cd MyApp
npx expo start

# Or bare workflow (more control, more setup)
npx @react-native-community/cli@latest init MyApp --new-architecture
cd MyApp
npx pod-install  # iOS only
npx react-native run-ios    # requires macOS + Xcode
npx react-native run-android  # requires Android Studio

Componentes principais

import {
  View, Text, StyleSheet, Pressable,
  ScrollView, FlatList, Image,
  TextInput, SafeAreaView, Platform,
} from 'react-native';

// No div, span, p — use View and Text instead
export default function HomeScreen() {
  return (
    <SafeAreaView style={styles.container}>
      <ScrollView>
        <Text style={styles.title}>Hello React Native!</Text>
        <Text style={styles.body}>
          This runs on iOS and Android natively.
        </Text>
        <Pressable
          style={({ pressed }) => [
            styles.button,
            pressed && styles.buttonPressed,
          ]}
          onPress={() => console.log('Pressed!')}
        >
          <Text style={styles.buttonText}>Tap Me</Text>
        </Pressable>
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    padding: 16,
    // Platform-specific
    ...Platform.select({
      ios: { fontFamily: 'SF Pro Display' },
      android: { fontFamily: 'Roboto' },
    }),
  },
  body: {
    fontSize: 16,
    color: '#555',
    paddingHorizontal: 16,
    lineHeight: 24,
  },
  button: {
    backgroundColor: '#0066CC',
    margin: 16,
    padding: 16,
    borderRadius: 12,
    alignItems: 'center',
  },
  buttonPressed: {
    opacity: 0.7,
    transform: [{ scale: 0.98 }],
  },
  buttonText: {
    color: 'white',
    fontWeight: '600',
    fontSize: 16,
  },
});

Navegação com React Navigation

npm install @react-navigation/native @react-navigation/native-stack
npm install react-native-screens react-native-safe-area-context

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

type RootStackParamList = {
  Home: undefined;
  Profile: { userId: number };
  Settings: undefined;
};

const Stack = createNativeStackNavigator<RootStackParamList>();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          headerStyle: { backgroundColor: '#0066CC' },
          headerTintColor: 'white',
        }}
      >
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Profile" component={ProfileScreen} />
        <Stack.Screen name="Settings" component={SettingsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// Navigate between screens
function HomeScreen({ navigation }) {
  return (
    <View>
      <Pressable onPress={() => navigation.navigate('Profile', { userId: 1 })}>
        <Text>Go to Profile</Text>
      </Pressable>
    </View>
  );
}

function ProfileScreen({ route, navigation }) {
  const { userId } = route.params;  // typed!
  return <Text>Profile {userId}</Text>;
}

Busca de dados

import { useQuery, useMutation, QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

// Wrap app
export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <NavigationContainer>...</NavigationContainer>
    </QueryClientProvider>
  );
}

// Fetch users
function UserList() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['users'],
    queryFn: () => fetch('https://api.example.com/users').then(r => r.json()),
  });

  if (isLoading) return <ActivityIndicator size="large" />;
  if (error) return <Text>Error: {error.message}</Text>;

  return (
    <FlatList
      data={data}
      keyExtractor={user => user.id.toString()}
      renderItem={({ item }) => (
        <View style={styles.userCard}>
          <Image source={{ uri: item.avatarUrl }} style={styles.avatar} />
          <Text style={styles.userName}>{item.name}</Text>
        </View>
      )}
    />
  );
}

Armazenamento Local e Estado

npm install @react-native-async-storage/async-storage
npm install zustand  # lightweight state management

import AsyncStorage from '@react-native-async-storage/async-storage';
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';

// Zustand store with AsyncStorage persistence
interface UserStore {
  user: User | null;
  token: string | null;
  setUser: (user: User, token: string) => void;
  logout: () => void;
}

export const useUserStore = create<UserStore>()(
  persist(
    (set) => ({
      user: null,
      token: null,
      setUser: (user, token) => set({ user, token }),
      logout: () => set({ user: null, token: null }),
    }),
    {
      name: 'user-storage',
      storage: createJSONStorage(() => AsyncStorage),
    }
  )
);

// Usage in component
function ProfileScreen() {
  const { user, logout } = useUserStore();
  return (
    <View>
      <Text>Welcome, {user?.name}!</Text>
      <Pressable onPress={logout}>
        <Text>Logout</Text>
      </Pressable>
    </View>
  );
}

Expo Router (Roteamento baseado em arquivo)

// app/(tabs)/index.tsx  → "/" tab
// app/(tabs)/profile.tsx → "/profile" tab
// app/[id].tsx → dynamic route

// Expo Router — Next.js-style for mobile
import { Stack, Tabs } from 'expo-router';

export default function RootLayout() {
  return <Stack />;
}

// app/(tabs)/_layout.tsx
export default function TabLayout() {
  return (
    <Tabs>
      <Tabs.Screen name="index" options={{ title: 'Home' }} />
      <Tabs.Screen name="profile" options={{ title: 'Profile' }} />
    </Tabs>
  );
}

Publicação em App Stores

# Expo EAS (Expo Application Services) — recommended
npm install -g eas-cli
eas login
eas build:configure

# Build for production
eas build --platform ios      # builds .ipa for App Store
eas build --platform android  # builds .aab for Play Store
eas build --platform all      # both simultaneously

# Submit to stores
eas submit --platform ios
eas submit --platform android

O React Native em 2026 está pronto para produção para a maioria dos casos de uso de aplicativos móveis. A nova arquitetura elimina a antiga ponte JavaScript, tornando as animações mais suaves e as chamadas de módulos nativos mais rápidas. Use o Expo para um desenvolvimento mais rápido e implantações mais simples – você sempre pode ejetar para um fluxo de trabalho simples se precisar de acesso nativo completo. Se você conhece o React, a curva de aprendizado do React Native pode ser gerenciada em 2 a 4 semanas.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা