Exemplos de React Native

Exemplos de desenvolvimento mobile multiplataforma React Native incluindo componentes, navegação, gerenciamento de estado e integração nativa

💻 Olá Mundo React Native typescript

🟢 simple

Exemplos básicos de aplicativos React Native com componentes, estilos e configuração de navegação

// React Native Hello World Examples

import React, { useState } from 'react';
import {
  StyleSheet,
  Text,
  View,
  Button,
  TextInput,
  TouchableOpacity,
  Image,
  ScrollView,
  Alert,
  SafeAreaView,
  StatusBar,
  Platform
} from 'react-native';

// 1. Basic Hello World Component
const HelloWorld = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hello, World!</Text>
      <Text style={styles.subtitle}>Welcome to React Native</Text>
    </View>
  );
};

// 2. Component with Props
interface GreetingProps {
  name: string;
  greeting?: string;
}

const Greeting: React.FC<GreetingProps> = ({ name, greeting = 'Hello' }) => {
  return (
    <View style={styles.card}>
      <Text style={styles.greeting}>{greeting}, {name}!</Text>
      <Text style={styles.message}>This component accepts props</Text>
    </View>
  );
};

// 3. Interactive Counter Component
const Counter: React.FC = () => {
  const [count, setCount] = useState(0);

  return (
    <View style={styles.card}>
      <Text style={styles.counterText}>Count: {count}</Text>
      <View style={styles.buttonRow}>
        <TouchableOpacity
          style={styles.button}
          onPress={() => setCount(count - 1)}
        >
          <Text style={styles.buttonText}>-</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={() => setCount(0)}
        >
          <Text style={styles.buttonText}>Reset</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={styles.button}
          onPress={() => setCount(count + 1)}
        >
          <Text style={styles.buttonText}>+</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

// 4. User Profile Component
interface UserProfileProps {
  initialName?: string;
  initialAge?: number;
}

const UserProfile: React.FC<UserProfileProps> = ({
  initialName = '',
  initialAge = 0
}) => {
  const [name, setName] = useState(initialName);
  const [age, setAge] = useState(initialAge.toString());
  const [isEditing, setIsEditing] = useState(false);

  const handleSave = () => {
    setIsEditing(false);
    Alert.alert('Profile Saved', `Name: ${name}, Age: ${age}`);
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>User Profile</Text>

      {isEditing ? (
        <View>
          <TextInput
            style={styles.input}
            value={name}
            onChangeText={setName}
            placeholder="Enter your name"
          />
          <TextInput
            style={styles.input}
            value={age}
            onChangeText={setAge}
            placeholder="Enter your age"
            keyboardType="numeric"
          />
          <View style={styles.buttonRow}>
            <TouchableOpacity
              style={[styles.button, styles.saveButton]}
              onPress={handleSave}
            >
              <Text style={styles.buttonText}>Save</Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={[styles.button, styles.cancelButton]}
              onPress={() => setIsEditing(false)}
            >
              <Text style={styles.buttonText}>Cancel</Text>
            </TouchableOpacity>
          </View>
        </View>
      ) : (
        <View>
          <Text style={styles.profileText}>Name: {name || 'Not set'}</Text>
          <Text style={styles.profileText}>Age: {age || 'Not set'}</Text>
          <TouchableOpacity
            style={[styles.button, styles.editButton]}
            onPress={() => setIsEditing(true)}
          >
            <Text style={styles.buttonText}>Edit Profile</Text>
          </TouchableOpacity>
        </View>
      )}
    </View>
  );
};

// 5. Todo List Component
interface Todo {
  id: number;
  text: string;
  completed: boolean;
  createdAt: Date;
}

const TodoApp: React.FC = () => {
  const [todos, setTodos] = useState<Todo[]>([
    { id: 1, text: 'Learn React Native', completed: false, createdAt: new Date() },
    { id: 2, text: 'Build a mobile app', completed: false, createdAt: new Date() }
  ]);
  const [newTodoText, setNewTodoText] = useState('');

  const addTodo = () => {
    if (newTodoText.trim()) {
      const newTodo: Todo = {
        id: Date.now(),
        text: newTodoText.trim(),
        completed: false,
        createdAt: new Date()
      };
      setTodos([newTodo, ...todos]);
      setNewTodoText('');
    }
  };

  const toggleTodo = (id: number) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id: number) => {
    Alert.alert(
      'Delete Todo',
      'Are you sure you want to delete this todo?',
      [
        { text: 'Cancel', style: 'cancel' },
        {
          text: 'Delete',
          style: 'destructive',
          onPress: () => setTodos(todos.filter(todo => todo.id !== id))
        }
      ]
    );
  };

  const completedCount = todos.filter(todo => todo.completed).length;
  const activeCount = todos.filter(todo => !todo.completed).length;

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Todo List</Text>

      <View style={styles.inputContainer}>
        <TextInput
          style={styles.todoInput}
          value={newTodoText}
          onChangeText={setNewTodoText}
          placeholder="What needs to be done?"
          onSubmitEditing={addTodo}
        />
        <TouchableOpacity style={styles.addButton} onPress={addTodo}>
          <Text style={styles.addButtonText}>+</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.statsContainer}>
        <Text style={styles.statText}>
          {activeCount} active, {completedCount} completed
        </Text>
      </View>

      <ScrollView style={styles.todoList}>
        {todos.map((todo) => (
          <View key={todo.id} style={styles.todoItem}>
            <TouchableOpacity
              style={styles.todoCheckbox}
              onPress={() => toggleTodo(todo.id)}
            >
              <View style={[
                styles.checkbox,
                todo.completed && styles.checkboxChecked
              ]}>
                {todo.completed && <Text style={styles.checkmark}>✓</Text>}
              </View>
            </TouchableOpacity>
            <View style={styles.todoContent}>
              <Text style={[
                styles.todoText,
                todo.completed && styles.todoTextCompleted
              ]}>
                {todo.text}
              </Text>
              <Text style={styles.todoDate}>
                {todo.createdAt.toLocaleDateString()}
              </Text>
            </View>
            <TouchableOpacity
              style={styles.deleteButton}
              onPress={() => deleteTodo(todo.id)}
            >
              <Text style={styles.deleteButtonText}>×</Text>
            </TouchableOpacity>
          </View>
        ))}
      </ScrollView>
    </View>
  );
};

// 6. Main App Component
const App: React.FC = () => {
  const [activeComponent, setActiveComponent] = useState<string>('all');

  const renderComponent = () => {
    switch (activeComponent) {
      case 'greeting':
        return <Greeting name="React Native Developer" />;
      case 'counter':
        return <Counter />;
      case 'profile':
        return <UserProfile initialName="John Doe" initialAge={25} />;
      case 'todo':
        return <TodoApp />;
      default:
        return (
          <>
            <HelloWorld />
            <Greeting name="Mobile Developer" />
            <Counter />
            <UserProfile />
            <TodoApp />
          </>
        );
    }
  };

  return (
    <SafeAreaView style={styles.safeArea}>
      <StatusBar
        barStyle="light-content"
        backgroundColor="#2c3e50"
      />

      <View style={styles.header}>
        <Text style={styles.headerTitle}>React Native Demo</Text>
        <Text style={styles.headerSubtitle}>
          Platform: {Platform.OS === 'ios' ? 'iOS' : 'Android'}
        </Text>
      </View>

      <View style={styles.navigation}>
        {['all', 'greeting', 'counter', 'profile', 'todo'].map((component) => (
          <TouchableOpacity
            key={component}
            style={[
              styles.navButton,
              activeComponent === component && styles.activeNavButton
            ]}
            onPress={() => setActiveComponent(component)}
          >
            <Text style={[
              styles.navButtonText,
              activeComponent === component && styles.activeNavButtonText
            ]}>
              {component.charAt(0).toUpperCase() + component.slice(1)}
            </Text>
          </TouchableOpacity>
        ))}
      </View>

      <ScrollView style={styles.content}>
        {renderComponent()}
      </ScrollView>
    </SafeAreaView>
  );
};

// Styles
const styles = StyleSheet.create({
  safeArea: {
    flex: 1,
    backgroundColor: '#f8f9fa',
  },
  container: {
    padding: 20,
    alignItems: 'center',
    backgroundColor: '#fff',
    margin: 16,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#2c3e50',
    marginBottom: 8,
  },
  subtitle: {
    fontSize: 16,
    color: '#7f8c8d',
    textAlign: 'center',
  },
  card: {
    backgroundColor: '#fff',
    margin: 16,
    padding: 20,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#2c3e50',
    marginBottom: 16,
    textAlign: 'center',
  },
  greeting: {
    fontSize: 20,
    fontWeight: '600',
    color: '#3498db',
    textAlign: 'center',
    marginBottom: 8,
  },
  message: {
    fontSize: 14,
    color: '#7f8c8d',
    textAlign: 'center',
  },
  counterText: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#2c3e50',
    textAlign: 'center',
    marginBottom: 16,
  },
  buttonRow: {
    flexDirection: 'row',
    justifyContent: 'center',
    gap: 12,
  },
  button: {
    backgroundColor: '#ecf0f1',
    paddingHorizontal: 20,
    paddingVertical: 12,
    borderRadius: 6,
    minWidth: 60,
    alignItems: 'center',
  },
  primaryButton: {
    backgroundColor: '#3498db',
  },
  saveButton: {
    backgroundColor: '#27ae60',
  },
  cancelButton: {
    backgroundColor: '#e74c3c',
  },
  editButton: {
    backgroundColor: '#f39c12',
  },
  buttonText: {
    color: '#2c3e50',
    fontSize: 16,
    fontWeight: '600',
  },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 6,
    padding: 12,
    fontSize: 16,
    marginBottom: 12,
    backgroundColor: '#fff',
  },
  profileText: {
    fontSize: 16,
    color: '#2c3e50',
    marginBottom: 8,
  },
  inputContainer: {
    flexDirection: 'row',
    marginBottom: 16,
  },
  todoInput: {
    flex: 1,
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 6,
    padding: 12,
    fontSize: 16,
    marginRight: 8,
  },
  addButton: {
    backgroundColor: '#27ae60',
    width: 48,
    height: 48,
    borderRadius: 6,
    justifyContent: 'center',
    alignItems: 'center',
  },
  addButtonText: {
    color: '#fff',
    fontSize: 24,
    fontWeight: 'bold',
  },
  statsContainer: {
    marginBottom: 16,
    padding: 12,
    backgroundColor: '#ecf0f1',
    borderRadius: 6,
  },
  statText: {
    textAlign: 'center',
    color: '#7f8c8d',
    fontSize: 14,
  },
  todoList: {
    maxHeight: 300,
  },
  todoItem: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 12,
    backgroundColor: '#fff',
    borderBottomWidth: 1,
    borderBottomColor: '#ecf0f1',
  },
  todoCheckbox: {
    marginRight: 12,
  },
  checkbox: {
    width: 24,
    height: 24,
    borderWidth: 2,
    borderColor: '#ddd',
    borderRadius: 4,
    justifyContent: 'center',
    alignItems: 'center',
  },
  checkboxChecked: {
    backgroundColor: '#27ae60',
    borderColor: '#27ae60',
  },
  checkmark: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
  todoContent: {
    flex: 1,
  },
  todoText: {
    fontSize: 16,
    color: '#2c3e50',
  },
  todoTextCompleted: {
    textDecorationLine: 'line-through',
    color: '#7f8c8d',
  },
  todoDate: {
    fontSize: 12,
    color: '#95a5a6',
    marginTop: 4,
  },
  deleteButton: {
    padding: 8,
    backgroundColor: '#e74c3c',
    borderRadius: 4,
  },
  deleteButtonText: {
    color: '#fff',
    fontSize: 18,
    fontWeight: 'bold',
  },
  header: {
    backgroundColor: '#2c3e50',
    padding: 20,
    paddingTop: Platform.OS === 'ios' ? 40 : 20,
  },
  headerTitle: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#fff',
    textAlign: 'center',
  },
  headerSubtitle: {
    fontSize: 14,
    color: '#ecf0f1',
    textAlign: 'center',
    marginTop: 4,
  },
  navigation: {
    flexDirection: 'row',
    backgroundColor: '#34495e',
    paddingVertical: 8,
  },
  navButton: {
    flex: 1,
    paddingVertical: 12,
    alignItems: 'center',
  },
  activeNavButton: {
    backgroundColor: '#2c3e50',
  },
  navButtonText: {
    color: '#ecf0f1',
    fontSize: 14,
    fontWeight: '500',
  },
  activeNavButtonText: {
    color: '#3498db',
    fontWeight: 'bold',
  },
  content: {
    flex: 1,
  },
});

export default App;

💻 Navegação React Native typescript

🟡 intermediate

Padrões de navegação e roteamento no React Native usando React Navigation

// React Native Navigation Examples

import React, { useState } from 'react';
import {
  StyleSheet,
  Text,
  View,
  Button,
  TouchableOpacity,
  Image,
  ScrollView,
  TextInput,
  Alert
} from 'react-native';
import {
  NavigationContainer,
  createNativeStackNavigator,
  NativeStackNavigationProp,
  NativeStackScreenProps,
} from '@react-navigation/native-stack';
import {
  createBottomTabNavigator,
  BottomTabNavigationProp,
} from '@react-navigation/bottom-tabs';
import {
  createDrawerNavigator,
  DrawerNavigationProp,
} from '@react-navigation/drawer';

// Type definitions
type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Settings: undefined;
  Details: { itemId: string };
  Modal: undefined;
};

type TabParamList = {
  HomeTab: undefined;
  SearchTab: undefined;
  ProfileTab: undefined;
};

type DrawerParamList = {
  HomeDrawer: undefined;
  SettingsDrawer: undefined;
  AboutDrawer: undefined;
};

// 1. Stack Navigation Example
const Stack = createNativeStackNavigator<RootStackParamList>();

interface HomeScreenProps {
  navigation: NativeStackNavigationProp<RootStackParamList, 'Home'>;
}

const HomeScreen: React.FC<HomeScreenProps> = ({ navigation }) => {
  const [items] = useState([
    { id: '1', title: 'First Item', description: 'This is the first item' },
    { id: '2', title: 'Second Item', description: 'This is the second item' },
    { id: '3', title: 'Third Item', description: 'This is the third item' },
  ]);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Home Screen</Text>

      <ScrollView style={styles.itemList}>
        {items.map((item) => (
          <TouchableOpacity
            key={item.id}
            style={styles.itemCard}
            onPress={() => navigation.navigate('Details', { itemId: item.id })}
          >
            <Text style={styles.itemTitle}>{item.title}</Text>
            <Text style={styles.itemDescription}>{item.description}</Text>
            <Text style={styles.seeMore}>See details →</Text>
          </TouchableOpacity>
        ))}
      </ScrollView>

      <View style={styles.buttonContainer}>
        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={() => navigation.navigate('Profile', { userId: 'user123' })}
        >
          <Text style={styles.buttonText}>Go to Profile</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={() => navigation.navigate('Modal')}
        >
          <Text style={styles.buttonText}>Open Modal</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

interface ProfileScreenProps {
  route: NativeStackScreenProps<RootStackParamList, 'Profile'>['route'];
  navigation: NativeStackNavigationProp<RootStackParamList, 'Profile'>;
}

const ProfileScreen: React.FC<ProfileScreenProps> = ({ route, navigation }) => {
  const { userId } = route.params;
  const [user, setUser] = useState({
    name: 'John Doe',
    email: '[email protected]',
    bio: 'Mobile app developer'
  });

  return (
    <View style={styles.container}>
      <View style={styles.profileHeader}>
        <View style={styles.avatar}>
          <Text style={styles.avatarText}>
            {user.name.split(' ').map(n => n[0]).join('')}
          </Text>
        </View>
        <Text style={styles.profileName}>{user.name}</Text>
        <Text style={styles.profileEmail}>{user.email}</Text>
      </View>

      <View style={styles.profileContent}>
        <Text style={styles.sectionTitle}>About</Text>
        <Text style={styles.bioText}>{user.bio}</Text>

        <Text style={styles.sectionTitle}>User ID</Text>
        <Text style={styles.userId}>{userId}</Text>

        <TouchableOpacity
          style={[styles.button, styles.editButton]}
          onPress={() => Alert.alert('Edit Profile', 'Profile editing coming soon!')}
        >
          <Text style={styles.buttonText}>Edit Profile</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.navButtons}>
        <TouchableOpacity
          style={[styles.navButton, styles.backButton]}
          onPress={() => navigation.goBack()}
        >
          <Text style={styles.navButtonText}>← Back</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.navButton, styles.settingsButton]}
          onPress={() => navigation.navigate('Settings')}
        >
          <Text style={styles.navButtonText}>Settings →</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

const DetailsScreen: React.FC<{
  route: NativeStackScreenProps<RootStackParamList, 'Details'>['route'];
  navigation: NativeStackNavigationProp<RootStackParamList, 'Details'>;
}> = ({ route, navigation }) => {
  const { itemId } = route.params;

  const itemDetails = {
    '1': { title: 'First Item', description: 'Detailed description of the first item', date: '2023-01-01' },
    '2': { title: 'Second Item', description: 'Detailed description of the second item', date: '2023-01-02' },
    '3': { title: 'Third Item', description: 'Detailed description of the third item', date: '2023-01-03' },
  };

  const item = itemDetails[itemId as keyof typeof itemDetails];

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Item Details</Text>

      {item ? (
        <View style={styles.detailsCard}>
          <Text style={styles.detailsTitle}>{item.title}</Text>
          <Text style={styles.detailsDescription}>{item.description}</Text>
          <Text style={styles.detailsDate}>Created: {item.date}</Text>
          <Text style={styles.itemIdText}>Item ID: {itemId}</Text>
        </View>
      ) : (
        <Text style={styles.notFound}>Item not found</Text>
      )}

      <TouchableOpacity
        style={[styles.button, styles.primaryButton]}
        onPress={() => navigation.goBack()}
      >
        <Text style={styles.buttonText}>Go Back</Text>
      </TouchableOpacity>
    </View>
  );
};

const SettingsScreen: React.FC<{
  navigation: NativeStackNavigationProp<RootStackParamList, 'Settings'>;
}> = ({ navigation }) => {
  const [notifications, setNotifications] = useState(true);
  const [darkMode, setDarkMode] = useState(false);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Settings</Text>

      <View style={styles.settingsSection}>
        <Text style={styles.sectionTitle}>Preferences</Text>

        <TouchableOpacity
          style={styles.settingItem}
          onPress={() => setNotifications(!notifications)}
        >
          <Text style={styles.settingText}>Push Notifications</Text>
          <View style={[styles.toggle, notifications && styles.toggleOn]}>
            <Text style={styles.toggleText}>
              {notifications ? 'ON' : 'OFF'}
            </Text>
          </View>
        </TouchableOpacity>

        <TouchableOpacity
          style={styles.settingItem}
          onPress={() => setDarkMode(!darkMode)}
        >
          <Text style={styles.settingText}>Dark Mode</Text>
          <View style={[styles.toggle, darkMode && styles.toggleOn]}>
            <Text style={styles.toggleText}>
              {darkMode ? 'ON' : 'OFF'}
            </Text>
          </View>
        </TouchableOpacity>
      </View>

      <View style={styles.buttonContainer}>
        <TouchableOpacity
          style={[styles.button, styles.dangerButton]}
          onPress={() => navigation.goBack()}
        >
          <Text style={styles.buttonText}>Back</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

const ModalScreen: React.FC<{
  navigation: NativeStackNavigationProp<RootStackParamList, 'Modal'>;
}> = ({ navigation }) => {
  return (
    <View style={styles.modalContainer}>
      <View style={styles.modalContent}>
        <Text style={styles.modalTitle}>Modal Screen</Text>
        <Text style={styles.modalMessage}>This is a modal that can be dismissed.</Text>

        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={() => navigation.goBack()}
        >
          <Text style={styles.buttonText}>Close Modal</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

// 2. Tab Navigation Example
const Tab = createBottomTabNavigator<TabParamList>();

const TabHomeScreen: React.FC = () => (
  <View style={styles.container}>
    <Text style={styles.title}>Tab Home</Text>
    <Text style={styles.subtitle}>This is the home tab</Text>
  </View>
);

const TabSearchScreen: React.FC = () => {
  const [searchText, setSearchText] = useState('');

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Search</Text>
      <TextInput
        style={styles.searchInput}
        placeholder="Search for something..."
        value={searchText}
        onChangeText={setSearchText}
      />
      <Text style={styles.searchResult}>
        {searchText ? `Searching for: "${searchText}"` : 'Enter search term'}
      </Text>
    </View>
  );
};

const TabProfileScreen: React.FC = () => (
  <View style={styles.container}>
    <Text style={styles.title}>Tab Profile</Text>
    <Text style={styles.subtitle}>This is the profile tab</Text>
  </View>
);

const TabNavigator: React.FC = () => {
  return (
    <Tab.Navigator
      screenOptions={({ route }) => ({
        tabBarIcon: ({ color, size }) => {
          let iconName = '';

          if (route.name === 'HomeTab') {
            iconName = '🏠';
          } else if (route.name === 'SearchTab') {
            iconName = '🔍';
          } else if (route.name === 'ProfileTab') {
            iconName = '👤';
          }

          return <Text style={{ fontSize: size, color }}>{iconName}</Text>;
        },
        tabBarActiveTintColor: '#3498db',
        tabBarInactiveTintColor: '#95a5a6',
        tabBarStyle: { backgroundColor: '#fff' },
      })}
    >
      <Tab.Screen
        name="HomeTab"
        component={TabHomeScreen}
        options={{ title: 'Home' }}
      />
      <Tab.Screen
        name="SearchTab"
        component={TabSearchScreen}
        options={{ title: 'Search' }}
      />
      <Tab.Screen
        name="ProfileTab"
        component={TabProfileScreen}
        options={{ title: 'Profile' }}
      />
    </Tab.Navigator>
  );
};

// 3. Complete App with Stack Navigation
const StackNavigator: React.FC = () => {
  return (
    <Stack.Navigator
      initialRouteName="Home"
      screenOptions={{
        headerStyle: { backgroundColor: '#3498db' },
        headerTintColor: '#fff',
        headerTitleStyle: { fontWeight: 'bold' },
      }}
    >
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'React Navigation Demo' }}
      />
      <Stack.Screen
        name="Profile"
        component={ProfileScreen}
        options={({ route }) => ({ title: `Profile - ${route.params.userId}` })}
      />
      <Stack.Screen
        name="Details"
        component={DetailsScreen}
        options={{ title: 'Item Details' }}
      />
      <Stack.Screen
        name="Settings"
        component={SettingsScreen}
        options={{ title: 'Settings' }}
      />
      <Stack.Screen
        name="Modal"
        component={ModalScreen}
        options={{
          presentation: 'modal',
          title: 'Modal',
          headerShown: false,
        }}
      />
    </Stack.Navigator>
  );
};

// 4. Main App Component
const NavigationApp: React.FC = () => {
  const [useTabs, setUseTabs] = useState(false);

  return (
    <NavigationContainer>
      {useTabs ? (
        <View style={styles.container}>
          <View style={styles.navigationToggle}>
            <TouchableOpacity
              style={[styles.toggleButton, useTabs && styles.activeToggle]}
              onPress={() => setUseTabs(true)}
            >
              <Text style={styles.toggleButtonText}>Tabs</Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={[styles.toggleButton, !useTabs && styles.activeToggle]}
              onPress={() => setUseTabs(false)}
            >
              <Text style={styles.toggleButtonText}>Stack</Text>
            </TouchableOpacity>
          </View>
          <TabNavigator />
        </View>
      ) : (
        <View style={styles.container}>
          <View style={styles.navigationToggle}>
            <TouchableOpacity
              style={[styles.toggleButton, useTabs && styles.activeToggle]}
              onPress={() => setUseTabs(true)}
            >
              <Text style={styles.toggleButtonText}>Tabs</Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={[styles.toggleButton, !useTabs && styles.activeToggle]}
              onPress={() => setUseTabs(false)}
            >
              <Text style={styles.toggleButtonText}>Stack</Text>
            </TouchableOpacity>
          </View>
          <StackNavigator />
        </View>
      )}
    </NavigationContainer>
  );
};

// Styles
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f9fa',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#2c3e50',
    textAlign: 'center',
    margin: 20,
  },
  subtitle: {
    fontSize: 16,
    color: '#7f8c8d',
    textAlign: 'center',
    marginBottom: 20,
  },
  itemList: {
    flex: 1,
    marginHorizontal: 20,
  },
  itemCard: {
    backgroundColor: '#fff',
    padding: 16,
    marginBottom: 12,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  itemTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 4,
  },
  itemDescription: {
    fontSize: 14,
    color: '#7f8c8d',
    marginBottom: 8,
  },
  seeMore: {
    fontSize: 12,
    color: '#3498db',
    textAlign: 'right',
  },
  buttonContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    padding: 20,
  },
  button: {
    paddingHorizontal: 20,
    paddingVertical: 12,
    borderRadius: 8,
    alignItems: 'center',
    minWidth: 120,
  },
  primaryButton: {
    backgroundColor: '#3498db',
  },
  secondaryButton: {
    backgroundColor: '#95a5a6',
  },
  dangerButton: {
    backgroundColor: '#e74c3c',
  },
  editButton: {
    backgroundColor: '#f39c12',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  profileHeader: {
    alignItems: 'center',
    marginBottom: 30,
  },
  avatar: {
    width: 80,
    height: 80,
    borderRadius: 40,
    backgroundColor: '#3498db',
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: 16,
  },
  avatarText: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#fff',
  },
  profileName: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#2c3e50',
    marginBottom: 4,
  },
  profileEmail: {
    fontSize: 14,
    color: '#7f8c8d',
  },
  profileContent: {
    paddingHorizontal: 20,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 8,
  },
  bioText: {
    fontSize: 16,
    color: '#34495e',
    marginBottom: 20,
  },
  userId: {
    fontSize: 14,
    color: '#7f8c8d',
    marginBottom: 20,
  },
  navButtons: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingHorizontal: 20,
    marginTop: 20,
  },
  navButton: {
    paddingHorizontal: 20,
    paddingVertical: 12,
    borderRadius: 8,
  },
  backButton: {
    backgroundColor: '#95a5a6',
  },
  settingsButton: {
    backgroundColor: '#f39c12',
  },
  navButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  detailsCard: {
    backgroundColor: '#fff',
    padding: 20,
    margin: 20,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  detailsTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#2c3e50',
    marginBottom: 8,
  },
  detailsDescription: {
    fontSize: 16,
    color: '#34495e',
    marginBottom: 12,
  },
  detailsDate: {
    fontSize: 14,
    color: '#7f8c8d',
    marginBottom: 8,
  },
  itemIdText: {
    fontSize: 12,
    color: '#95a5a6',
  },
  notFound: {
    fontSize: 16,
    color: '#e74c3c',
    textAlign: 'center',
    margin: 20,
  },
  settingsSection: {
    margin: 20,
  },
  settingItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#ecf0f1',
  },
  settingText: {
    fontSize: 16,
    color: '#2c3e50',
  },
  toggle: {
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 12,
    backgroundColor: '#ecf0f1',
  },
  toggleOn: {
    backgroundColor: '#27ae60',
  },
  toggleText: {
    fontSize: 12,
    fontWeight: '600',
    color: '#7f8c8d',
  },
  toggleOnText: {
    color: '#fff',
  },
  modalContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
  },
  modalContent: {
    backgroundColor: '#fff',
    padding: 30,
    borderRadius: 12,
    alignItems: 'center',
    margin: 20,
  },
  modalTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#2c3e50',
    marginBottom: 12,
  },
  modalMessage: {
    fontSize: 16,
    color: '#7f8c8d',
    textAlign: 'center',
    marginBottom: 20,
  },
  searchInput: {
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    padding: 12,
    fontSize: 16,
    margin: 20,
  },
  searchResult: {
    fontSize: 16,
    color: '#7f8c8d',
    textAlign: 'center',
    marginHorizontal: 20,
  },
  navigationToggle: {
    flexDirection: 'row',
    backgroundColor: '#34495e',
    padding: 4,
  },
  toggleButton: {
    flex: 1,
    paddingVertical: 12,
    alignItems: 'center',
    borderRadius: 4,
  },
  activeToggle: {
    backgroundColor: '#3498db',
  },
  toggleButtonText: {
    color: '#ecf0f1',
    fontSize: 14,
    fontWeight: '500',
  },
});

export default NavigationApp;

💻 Gerenciamento de Estado React Native typescript

🟡 intermediate

Padrões de gerenciamento de estado no React Native incluindo Redux, Context API e React Query

// React Native State Management Examples

import React, { useState, useContext, createContext, useReducer, useEffect } from 'react';
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  TextInput,
  ScrollView,
  Alert,
  ActivityIndicator
} from 'react-native';

// 1. useState and Local State Management
const LocalStateExample: React.FC = () => {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: '',
  });

  const [errors, setErrors] = useState<Record<string, string>>({});
  const [isSubmitting, setIsSubmitting] = useState(false);

  const validateForm = () => {
    const newErrors: Record<string, string> = {};

    if (!user.name.trim()) {
      newErrors.name = 'Name is required';
    }

    if (!user.email.trim()) {
      newErrors.email = 'Email is required';
    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(user.email)) {
      newErrors.email = 'Please enter a valid email';
    }

    if (!user.age.trim()) {
      newErrors.age = 'Age is required';
    } else if (parseInt(user.age) < 18) {
      newErrors.age = 'You must be at least 18 years old';
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSubmit = async () => {
    if (!validateForm()) return;

    setIsSubmitting(true);

    // Simulate API call
    await new Promise(resolve => setTimeout(resolve, 2000));

    Alert.alert('Success', 'Form submitted successfully!');
    setIsSubmitting(false);
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Local State Management</Text>

      <View style={styles.inputGroup}>
        <Text style={styles.label}>Name</Text>
        <TextInput
          style={[styles.input, errors.name && styles.inputError]}
          value={user.name}
          onChangeText={(text) => setUser({ ...user, name: text })}
          placeholder="Enter your name"
        />
        {errors.name && <Text style={styles.errorText}>{errors.name}</Text>}
      </View>

      <View style={styles.inputGroup}>
        <Text style={styles.label}>Email</Text>
        <TextInput
          style={[styles.input, errors.email && styles.inputError]}
          value={user.email}
          onChangeText={(text) => setUser({ ...user, email: text })}
          placeholder="Enter your email"
          keyboardType="email-address"
        />
        {errors.email && <Text style={styles.errorText}>{errors.email}</Text>}
      </View>

      <View style={styles.inputGroup}>
        <Text style={styles.label}>Age</Text>
        <TextInput
          style={[styles.input, errors.age && styles.inputError]}
          value={user.age}
          onChangeText={(text) => setUser({ ...user, age: text })}
          placeholder="Enter your age"
          keyboardType="numeric"
        />
        {errors.age && <Text style={styles.errorText}>{errors.age}</Text>}
      </View>

      <TouchableOpacity
        style={[styles.button, styles.primaryButton]}
        onPress={handleSubmit}
        disabled={isSubmitting}
      >
        {isSubmitting ? (
          <ActivityIndicator color="#fff" />
        ) : (
          <Text style={styles.buttonText}>Submit</Text>
        )}
      </TouchableOpacity>

      <View style={styles.debugInfo}>
        <Text style={styles.debugTitle}>Current State:</Text>
        <Text style={styles.debugText}>{JSON.stringify(user, null, 2)}</Text>
      </View>
    </View>
  );
};

// 2. Context API for Global State
interface AppState {
  theme: 'light' | 'dark';
  user: User | null;
  notifications: Notification[];
}

interface User {
  id: string;
  name: string;
  email: string;
}

interface Notification {
  id: string;
  message: string;
  timestamp: Date;
}

interface AppContextType {
  state: AppState;
  setTheme: (theme: 'light' | 'dark') => void;
  setUser: (user: User | null) => void;
  addNotification: (message: string) => void;
  clearNotifications: () => void;
}

const AppContext = createContext<AppContextType | null>(null);

export const useAppContext = () => {
  const context = useContext(AppContext);
  if (!context) {
    throw new Error('useAppContext must be used within an AppProvider');
  }
  return context;
};

const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [state, setState] = useState<AppState>({
    theme: 'light',
    user: null,
    notifications: [],
  });

  const setTheme = (theme: 'light' | 'dark') => {
    setState(prev => ({ ...prev, theme }));
  };

  const setUser = (user: User | null) => {
    setState(prev => ({ ...prev, user }));
  };

  const addNotification = (message: string) => {
    const notification: Notification = {
      id: Date.now().toString(),
      message,
      timestamp: new Date(),
    };
    setState(prev => ({
      ...prev,
      notifications: [notification, ...prev.notifications].slice(0, 5),
    }));
  };

  const clearNotifications = () => {
    setState(prev => ({ ...prev, notifications: [] }));
  };

  return (
    <AppContext.Provider value={{
      state,
      setTheme,
      setUser,
      addNotification,
      clearNotifications,
    }}>
      {children}
    </AppContext.Provider>
  );
};

const ThemeToggle: React.FC = () => {
  const { state, setTheme } = useAppContext();

  return (
    <TouchableOpacity
      style={[
        styles.themeToggle,
        state.theme === 'dark' && styles.themeToggleDark
      ]}
      onPress={() => setTheme(state.theme === 'light' ? 'dark' : 'light')}
    >
      <Text style={styles.themeToggleText}>
        {state.theme === 'light' ? '🌞' : '🌙'} {state.theme === 'light' ? 'Light' : 'Dark'}
      </Text>
    </TouchableOpacity>
  );
};

const UserProfile: React.FC = () => {
  const { state, setUser } = useAppContext();

  const handleLogin = () => {
    const user: User = {
      id: '1',
      name: 'John Doe',
      email: '[email protected]',
    };
    setUser(user);
  };

  const handleLogout = () => {
    setUser(null);
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>User Profile</Text>

      {state.user ? (
        <View>
          <Text style={styles.userInfo}>Name: {state.user.name}</Text>
          <Text style={styles.userInfo}>Email: {state.user.email}</Text>
          <Text style={styles.userInfo}>ID: {state.user.id}</Text>
          <TouchableOpacity
            style={[styles.button, styles.dangerButton]}
            onPress={handleLogout}
          >
            <Text style={styles.buttonText}>Logout</Text>
          </TouchableOpacity>
        </View>
      ) : (
        <View>
          <Text style={styles.placeholderText}>Not logged in</Text>
          <TouchableOpacity
            style={[styles.button, styles.primaryButton]}
            onPress={handleLogin}
          >
            <Text style={styles.buttonText}>Login</Text>
          </TouchableOpacity>
        </View>
      )}
    </View>
  );
};

const NotificationPanel: React.FC = () => {
  const { state, addNotification, clearNotifications } = useAppContext();

  const handleAddNotification = () => {
    const messages = [
      'New message received',
      'Your profile was updated',
      'System maintenance scheduled',
      'New feature available',
    ];
    const randomMessage = messages[Math.floor(Math.random() * messages.length)];
    addNotification(randomMessage);
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Notifications</Text>

      <TouchableOpacity
        style={[styles.button, styles.secondaryButton]}
        onPress={handleAddNotification}
      >
        <Text style={styles.buttonText}>Add Notification</Text>
      </TouchableOpacity>

      {state.notifications.length > 0 && (
        <TouchableOpacity
          style={[styles.button, styles.clearButton]}
          onPress={clearNotifications}
        >
          <Text style={styles.buttonText}>Clear All</Text>
        </TouchableOpacity>
      )}

      <ScrollView style={styles.notificationList}>
        {state.notifications.map((notification) => (
          <View key={notification.id} style={styles.notificationItem}>
            <Text style={styles.notificationText}>{notification.message}</Text>
            <Text style={styles.notificationTime}>
              {notification.timestamp.toLocaleTimeString()}
            </Text>
          </View>
        ))}
      </ScrollView>

      {state.notifications.length === 0 && (
        <Text style={styles.placeholderText}>No notifications</Text>
      )}
    </View>
  );
};

// 3. useReducer for Complex State
interface Todo {
  id: string;
  text: string;
  completed: boolean;
  createdAt: Date;
}

type TodoAction =
  | { type: 'ADD_TODO'; text: string }
  | { type: 'TOGGLE_TODO'; id: string }
  | { type: 'DELETE_TODO'; id: string }
  | { type: 'EDIT_TODO'; id: string; text: string }
  | { type: 'CLEAR_COMPLETED' };

const todoReducer = (state: Todo[], action: TodoAction): Todo[] => {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        {
          id: Date.now().toString(),
          text: action.text,
          completed: false,
          createdAt: new Date(),
        },
        ...state,
      ];

    case 'TOGGLE_TODO':
      return state.map((todo) =>
        todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
      );

    case 'DELETE_TODO':
      return state.filter((todo) => todo.id !== action.id);

    case 'EDIT_TODO':
      return state.map((todo) =>
        todo.id === action.id ? { ...todo, text: action.text } : todo
      );

    case 'CLEAR_COMPLETED':
      return state.filter((todo) => !todo.completed);

    default:
      return state;
  }
};

const TodoReducerExample: React.FC = () => {
  const [todos, dispatch] = useReducer(todoReducer, []);
  const [newTodoText, setNewTodoText] = useState('');

  const addTodo = () => {
    if (newTodoText.trim()) {
      dispatch({ type: 'ADD_TODO', text: newTodoText.trim() });
      setNewTodoText('');
    }
  };

  const toggleTodo = (id: string) => {
    dispatch({ type: 'TOGGLE_TODO', id });
  };

  const deleteTodo = (id: string) => {
    Alert.alert(
      'Delete Todo',
      'Are you sure you want to delete this todo?',
      [
        { text: 'Cancel', style: 'cancel' },
        { text: 'Delete', style: 'destructive', onPress: () => dispatch({ type: 'DELETE_TODO', id }) }
      ]
    );
  };

  const editTodo = (id: string, currentText: string) => {
    Alert.prompt(
      'Edit Todo',
      'Edit your todo:',
      [
        { text: 'Cancel', style: 'cancel' },
        {
          text: 'Save',
          onPress: (newText) => {
            if (newText && newText.trim()) {
              dispatch({ type: 'EDIT_TODO', id, text: newText.trim() });
            }
          },
        },
      ],
      'plain-text',
      currentText
    );
  };

  const completedCount = todos.filter(todo => todo.completed).length;
  const activeCount = todos.filter(todo => !todo.completed).length;

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>useReducer Todo App</Text>

      <View style={styles.inputGroup}>
        <TextInput
          style={styles.input}
          value={newTodoText}
          onChangeText={setNewTodoText}
          placeholder="What needs to be done?"
          onSubmitEditing={addTodo}
        />
        <TouchableOpacity style={[styles.button, styles.addButton]} onPress={addTodo}>
          <Text style={styles.addButtonText}>+</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.statsContainer}>
        <Text style={styles.statText}>
          {activeCount} active, {completedCount} completed
        </Text>
        {completedCount > 0 && (
          <TouchableOpacity
            style={[styles.button, styles.clearButton]}
            onPress={() => dispatch({ type: 'CLEAR_COMPLETED' })}
          >
            <Text style={styles.buttonTextSmall}>Clear Completed</Text>
          </TouchableOpacity>
        )}
      </View>

      <ScrollView style={styles.todoList}>
        {todos.map((todo) => (
          <View key={todo.id} style={styles.todoItem}>
            <TouchableOpacity
              style={styles.todoCheckbox}
              onPress={() => toggleTodo(todo.id)}
            >
              <View style={[styles.checkbox, todo.completed && styles.checkboxChecked]}>
                {todo.completed && <Text style={styles.checkmark}>✓</Text>}
              </View>
            </TouchableOpacity>
            <View style={styles.todoContent}>
              <TouchableOpacity
                style={styles.todoTextContainer}
                onPress={() => editTodo(todo.id, todo.text)}
              >
                <Text style={[styles.todoText, todo.completed && styles.todoTextCompleted]}>
                  {todo.text}
                </Text>
              </TouchableOpacity>
              <Text style={styles.todoDate}>
                {todo.createdAt.toLocaleDateString()}
              </Text>
            </View>
            <TouchableOpacity
              style={styles.deleteButton}
              onPress={() => deleteTodo(todo.id)}
            >
              <Text style={styles.deleteButtonText}>×</Text>
            </TouchableOpacity>
          </View>
        ))}
      </ScrollView>

      {todos.length === 0 && (
        <Text style={styles.placeholderText}>No todos yet. Add one above!</Text>
      )}

      <View style={styles.debugInfo}>
        <Text style={styles.debugTitle}>State (useReducer):</Text>
        <Text style={styles.debugText}>{JSON.stringify(todos.slice(0, 2), null, 2)}</Text>
        {todos.length > 2 && <Text style={styles.debugText}>...and {todos.length - 2} more items</Text>}
      </View>
    </View>
  );
};

// 4. Custom Hook for Data Fetching
interface UseDataResult<T> {
  data: T | null;
  loading: boolean;
  error: string | null;
  refetch: () => void;
}

function useData<T>(fetchFunction: () => Promise<T>): UseDataResult<T> {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const fetchData = async () => {
    setLoading(true);
    setError(null);

    try {
      const result = await fetchFunction();
      setData(result);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'An error occurred');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchData();
  }, []);

  return { data, loading, error, refetch: fetchData };
}

// API simulation functions
const fetchUser = async (): Promise<User> => {
  await new Promise(resolve => setTimeout(resolve, 1500));
  return {
    id: '1',
    name: 'Jane Smith',
    email: '[email protected]',
  };
};

const fetchPosts = async (): Promise<Array<{ id: string; title: string; body: string }>> => {
  await new Promise(resolve => setTimeout(resolve, 2000));
  return [
    { id: '1', title: 'First Post', body: 'This is the first post' },
    { id: '2', title: 'Second Post', body: 'This is the second post' },
    { id: '3', title: 'Third Post', body: 'This is the third post' },
  ];
};

const DataFetchingExample: React.FC = () => {
  const { data: user, loading: userLoading, error: userError, refetch: refetchUser } = useData(fetchUser);
  const { data: posts, loading: postsLoading, error: postsError, refetch: refetchPosts } = useData(fetchPosts);

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Custom Hook Data Fetching</Text>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>User Data</Text>
        {userLoading && <ActivityIndicator color="#3498db" />}
        {userError && <Text style={styles.errorText}>Error: {userError}</Text>}
        {user && (
          <View style={styles.dataDisplay}>
            <Text style={styles.dataLabel}>Name: {user.name}</Text>
            <Text style={styles.dataLabel}>Email: {user.email}</Text>
          </View>
        )}
        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={refetchUser}
          disabled={userLoading}
        >
          <Text style={styles.buttonText}>Refresh User</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Posts Data</Text>
        {postsLoading && <ActivityIndicator color="#3498db" />}
        {postsError && <Text style={styles.errorText}>Error: {postsError}</Text>}
        {posts && (
          <ScrollView style={styles.dataList}>
            {posts.map((post) => (
              <View key={post.id} style={styles.postItem}>
                <Text style={styles.postTitle}>{post.title}</Text>
                <Text style={styles.postBody}>{post.body}</Text>
              </View>
            ))}
          </ScrollView>
        )}
        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={refetchPosts}
          disabled={postsLoading}
        >
          <Text style={styles.buttonText}>Refresh Posts</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

// 5. Main App Component with Context Provider
const StateManagementApp: React.FC = () => {
  return (
    <AppProvider>
      <ScrollView style={styles.container}>
        <View style={styles.header}>
          <Text style={styles.headerTitle}>State Management Examples</Text>
          <ThemeToggle />
        </View>

        <LocalStateExample />
        <UserProfile />
        <NotificationPanel />
        <TodoReducerExample />
        <DataFetchingExample />
      </ScrollView>
    </AppProvider>
  );
};

// Styles
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f9fa',
  },
  header: {
    padding: 20,
    backgroundColor: '#3498db',
    alignItems: 'center',
  },
  headerTitle: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#fff',
    marginBottom: 16,
    textAlign: 'center',
  },
  themeToggle: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#ecf0f1',
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 20,
  },
  themeToggleDark: {
    backgroundColor: '#34495e',
  },
  themeToggleText: {
    fontSize: 16,
    fontWeight: '500',
  },
  card: {
    backgroundColor: '#fff',
    margin: 16,
    padding: 20,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#2c3e50',
    marginBottom: 16,
    textAlign: 'center',
  },
  inputGroup: {
    marginBottom: 16,
  },
  label: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 8,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 6,
    padding: 12,
    fontSize: 16,
    backgroundColor: '#fff',
  },
  inputError: {
    borderColor: '#e74c3c',
  },
  errorText: {
    color: '#e74c3c',
    fontSize: 14,
    marginTop: 4,
  },
  button: {
    paddingVertical: 12,
    paddingHorizontal: 20,
    borderRadius: 6,
    alignItems: 'center',
    marginTop: 8,
  },
  primaryButton: {
    backgroundColor: '#3498db',
  },
  secondaryButton: {
    backgroundColor: '#95a5a6',
  },
  dangerButton: {
    backgroundColor: '#e74c3c',
  },
  clearButton: {
    backgroundColor: '#f39c12',
  },
  addButton: {
    backgroundColor: '#27ae60',
    width: 48,
    height: 48,
    borderRadius: 6,
    justifyContent: 'center',
    alignItems: 'center',
    marginLeft: 8,
  },
  addButtonText: {
    color: '#fff',
    fontSize: 24,
    fontWeight: 'bold',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  buttonTextSmall: {
    color: '#fff',
    fontSize: 14,
    fontWeight: '600',
  },
  userInfo: {
    fontSize: 16,
    color: '#2c3e50',
    marginBottom: 8,
  },
  placeholderText: {
    fontSize: 16,
    color: '#7f8c8d',
    textAlign: 'center',
    marginVertical: 16,
  },
  debugInfo: {
    marginTop: 20,
    padding: 12,
    backgroundColor: '#2c3e50',
    borderRadius: 6,
  },
  debugTitle: {
    fontSize: 14,
    fontWeight: '600',
    color: '#ecf0f1',
    marginBottom: 8,
  },
  debugText: {
    fontSize: 12,
    color: '#bdc3c7',
    fontFamily: 'monospace',
  },
  notificationList: {
    maxHeight: 200,
    marginTop: 16,
  },
  notificationItem: {
    backgroundColor: '#ecf0f1',
    padding: 12,
    marginBottom: 8,
    borderRadius: 6,
    borderLeftWidth: 4,
    borderLeftColor: '#3498db',
  },
  notificationText: {
    fontSize: 14,
    color: '#2c3e50',
    marginBottom: 4,
  },
  notificationTime: {
    fontSize: 12,
    color: '#7f8c8d',
  },
  statsContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 8,
    marginBottom: 16,
  },
  statText: {
    fontSize: 14,
    color: '#7f8c8d',
  },
  todoList: {
    maxHeight: 300,
  },
  todoItem: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingVertical: 8,
    borderBottomWidth: 1,
    borderBottomColor: '#ecf0f1',
  },
  todoCheckbox: {
    marginRight: 12,
  },
  checkbox: {
    width: 24,
    height: 24,
    borderWidth: 2,
    borderColor: '#ddd',
    borderRadius: 4,
    justifyContent: 'center',
    alignItems: 'center',
  },
  checkboxChecked: {
    backgroundColor: '#27ae60',
    borderColor: '#27ae60',
  },
  checkmark: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
  todoContent: {
    flex: 1,
  },
  todoTextContainer: {
    flex: 1,
  },
  todoText: {
    fontSize: 16,
    color: '#2c3e50',
  },
  todoTextCompleted: {
    textDecorationLine: 'line-through',
    color: '#7f8c8d',
  },
  todoDate: {
    fontSize: 12,
    color: '#95a5a6',
    marginTop: 2,
  },
  deleteButton: {
    padding: 8,
    backgroundColor: '#e74c3c',
    borderRadius: 4,
    marginLeft: 8,
  },
  deleteButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
  section: {
    marginBottom: 24,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 12,
  },
  dataDisplay: {
    backgroundColor: '#f8f9fa',
    padding: 12,
    borderRadius: 6,
    marginBottom: 12,
  },
  dataLabel: {
    fontSize: 16,
    color: '#2c3e50',
    marginBottom: 4,
  },
  dataList: {
    maxHeight: 200,
    marginBottom: 12,
  },
  postItem: {
    backgroundColor: '#f8f9fa',
    padding: 12,
    marginBottom: 8,
    borderRadius: 6,
  },
  postTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 4,
  },
  postBody: {
    fontSize: 14,
    color: '#7f8c8d',
  },
});

export default StateManagementApp;

💻 Integração Nativa React Native typescript

🔴 complex

Integração de módulos nativos, código específico de plataforma e ponte do React Native com APIs nativas

// React Native Native Integration Examples

import React, { useState, useEffect, useRef } from 'react';
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  ScrollView,
  Alert,
  NativeModules,
  Platform,
  PermissionsAndroid,
  Linking,
  Share,
  Dimensions,
  AppState,
  DeviceEventEmitter
} from 'react-native';
import { CameraRoll } from '@react-native-community/cameraroll';
import Geolocation from '@react-native-community/geolocation';

// 1. Platform-specific code
const PlatformSpecificExample: React.FC = () => {
  const [platformInfo, setPlatformInfo] = useState({});

  useEffect(() => {
    setPlatformInfo({
      os: Platform.OS,
      version: Platform.Version,
      isPad: Platform.isPad,
      isTVOS: Platform.isTVOS,
      constants: Platform.constants,
    });
  }, []);

  const handlePlatformAction = () => {
    if (Platform.OS === 'ios') {
      Alert.alert('iOS Feature', 'This is an iOS-specific feature');
    } else if (Platform.OS === 'android') {
      Alert.alert('Android Feature', 'This is an Android-specific feature');
    }
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Platform-Specific Code</Text>

      <View style={styles.platformInfo}>
        <Text style={styles.infoLabel}>Platform: {Platform.OS}</Text>
        <Text style={styles.infoLabel}>Version: {Platform.Version}</Text>
        {Platform.OS === 'ios' && (
          <>
            <Text style={styles.infoLabel}>Is iPad: {Platform.isPad ? 'Yes' : 'No'}</Text>
            <Text style={styles.infoLabel}>Is TV: {Platform.isTVOS ? 'Yes' : 'No'}</Text>
          </>
        )}
      </View>

      <TouchableOpacity
        style={[styles.button, styles.primaryButton]}
        onPress={handlePlatformAction}
      >
        <Text style={styles.buttonText}>
          {Platform.OS === 'ios' ? 'iOS Action' : 'Android Action'}
        </Text>
      </TouchableOpacity>

      <View style={styles.platformSpecificUI}>
        {Platform.OS === 'ios' ? (
          <View style={styles.iosUI}>
            <Text style={styles.iosLabel}>iOS UI Elements</Text>
            <View style={styles.iosButton}>
              <Text style={styles.iosButtonText}>iOS Button</Text>
            </View>
          </View>
        ) : (
          <View style={styles.androidUI}>
            <Text style={styles.androidLabel}>Android UI Elements</Text>
            <View style={styles.androidButton}>
              <Text style={styles.androidButtonText}>Android Button</Text>
            </View>
          </View>
        )}
      </View>
    </View>
  );
};

// 2. Device APIs Integration
const DeviceAPIsExample: React.FC = () => {
  const [location, setLocation] = useState(null);
  const [dimensions, setDimensions] = useState(Dimensions.get('window'));
  const [appState, setAppState] = useState(AppState.currentState);
  const [shareContent, setShareContent] = useState('Check out this React Native app!');

  useEffect(() => {
    const dimensionHandler = ({ window }) => setDimensions(window);
    const subscription = Dimensions.addEventListener('change', dimensionHandler);

    const appStateHandler = (nextAppState) => setAppState(nextAppState);
    const appStateSubscription = AppState.addEventListener('change', appStateHandler);

    return () => {
      subscription?.remove();
      appStateSubscription?.remove();
    };
  }, []);

  const getCurrentLocation = () => {
    Geolocation.getCurrentPosition(
      (position) => {
        setLocation({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
        });
      },
      (error) => {
        Alert.alert('Error', 'Unable to get location');
      },
      { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
    );
  };

  const watchLocation = () => {
    const watchId = Geolocation.watchPosition(
      (position) => {
        setLocation({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          accuracy: position.coords.accuracy,
        });
      },
      (error) => {
        Alert.alert('Error', 'Unable to watch location');
      },
      { enableHighAccuracy: true, distanceFilter: 10 }
    );

    Alert.alert('Watching Location', 'Location updates started');
  };

  const shareContentAction = async () => {
    try {
      await Share.share({
        message: shareContent,
        url: 'https://reactnative.dev',
      });
    } catch (error) {
      Alert.alert('Error', 'Unable to share content');
    }
  };

  const openExternalApp = async () => {
    const url = 'https://reactnative.dev';
    const supported = await Linking.canOpenURL(url);

    if (supported) {
      await Linking.openURL(url);
    } else {
      Alert.alert('Error', 'Unable to open URL');
    }
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Device APIs Integration</Text>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Screen Dimensions</Text>
        <Text style={styles.infoLabel}>Width: {dimensions.width}</Text>
        <Text style={styles.infoLabel}>Height: {dimensions.height}</Text>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>App State: {appState}</Text>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Location Services</Text>
        {location ? (
          <View style={styles.locationInfo}>
            <Text style={styles.infoLabel}>Latitude: {location.latitude}</Text>
            <Text style={styles.infoLabel}>Longitude: {location.longitude}</Text>
            {location.accuracy && (
              <Text style={styles.infoLabel}>Accuracy: {location.accuracy}m</Text>
            )}
          </View>
        ) : (
          <Text style={styles.placeholderText}>No location data</Text>
        )}

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={getCurrentLocation}
        >
          <Text style={styles.buttonText}>Get Current Location</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={watchLocation}
        >
          <Text style={styles.buttonText}>Watch Location</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>External Integration</Text>

        <View style={styles.shareContainer}>
          <TextInput
            style={styles.shareInput}
            value={shareContent}
            onChangeText={setShareContent}
            placeholder="Enter content to share"
          />
          <TouchableOpacity
            style={[styles.button, styles.shareButton]}
            onPress={shareContentAction}
          >
            <Text style={styles.buttonText}>Share</Text>
          </TouchableOpacity>
        </View>

        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={openExternalApp}
        >
          <Text style={styles.buttonText}>Open React Native Website</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

// 3. Permissions Management
const PermissionsExample: React.FC = () => {
  const [permissions, setPermissions] = useState({});

  const requestLocationPermission = async () => {
    if (Platform.OS === 'android') {
      try {
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          {
            title: 'Location Permission',
            message: 'This app needs access to your location',
            buttonNeutral: 'Ask Me Later',
            buttonNegative: 'Cancel',
            buttonPositive: 'OK',
          }
        );

        setPermissions(prev => ({
          ...prev,
          location: granted === PermissionsAndroid.RESULTS.GRANTED,
        }));

        if (granted === PermissionsAndroid.RESULTS.GRANTED) {
          Alert.alert('Success', 'Location permission granted');
        } else {
          Alert.alert('Error', 'Location permission denied');
        }
      } catch (err) {
        Alert.alert('Error', 'Unable to request location permission');
      }
    } else {
      Alert.alert('Info', 'Location permissions are handled differently on iOS');
    }
  };

  const requestCameraPermission = async () => {
    if (Platform.OS === 'android') {
      try {
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.CAMERA,
          {
            title: 'Camera Permission',
            message: 'This app needs access to your camera',
            buttonNeutral: 'Ask Me Later',
            buttonNegative: 'Cancel',
            buttonPositive: 'OK',
          }
        );

        setPermissions(prev => ({
          ...prev,
          camera: granted === PermissionsAndroid.RESULTS.GRANTED,
        }));

        Alert.alert(
          'Camera Permission',
          granted === PermissionsAndroid.RESULTS.GRANTED ? 'Granted' : 'Denied'
        );
      } catch (err) {
        Alert.alert('Error', 'Unable to request camera permission');
      }
    } else {
      Alert.alert('Info', 'Camera permissions are handled differently on iOS');
    }
  };

  const checkPermission = async (permission: string) => {
    if (Platform.OS === 'android') {
      try {
        const hasPermission = await PermissionsAndroid.check(permission);
        Alert.alert('Permission Status', hasPermission ? 'Granted' : 'Not Granted');
      } catch (err) {
        Alert.alert('Error', 'Unable to check permission');
      }
    }
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Permissions Management</Text>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Location Permission</Text>
        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={requestLocationPermission}
        >
          <Text style={styles.buttonText}>Request Location Permission</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={() => checkPermission(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION)}
        >
          <Text style={styles.buttonText}>Check Location Permission</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Camera Permission</Text>
        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={requestCameraPermission}
        >
          <Text style={styles.buttonText}>Request Camera Permission</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={() => checkPermission(PermissionsAndroid.PERMISSIONS.CAMERA)}
        >
          <Text style={styles.buttonText}>Check Camera Permission</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.permissionsStatus}>
        <Text style={styles.sectionTitle}>Current Permissions Status</Text>
        {Object.entries(permissions).map(([key, value]) => (
          <Text key={key} style={styles.infoLabel}>
            {key}: {value ? '✓ Granted' : '✗ Denied'}
          </Text>
        ))}
      </View>
    </View>
  );
};

// 4. Native Module Example (Simulation)
const NativeModuleExample: React.FC = () => {
  const [batteryLevel, setBatteryLevel] = useState(null);
  const [deviceInfo, setDeviceInfo] = useState({});

  // Simulating native module calls
  const getBatteryLevel = async () => {
    // This would normally call a native module
    // For example: const level = await NativeModules.Battery.getLevel();

    // Simulate battery level
    const simulatedLevel = Math.random() * 100;
    setBatteryLevel(simulatedLevel.toFixed(1));

    Alert.alert('Battery Level', `Current battery: ${simulatedLevel.toFixed(1)}%`);
  };

  const getDeviceInfo = async () => {
    // This would normally call a native module
    // For example: const info = await NativeModules.DeviceInfo.getInfo();

    const simulatedInfo = {
      model: Platform.OS === 'ios' ? 'iPhone Simulator' : 'Android Emulator',
      brand: Platform.OS === 'ios' ? 'Apple' : 'Google',
      systemVersion: Platform.Version,
    };

    setDeviceInfo(simulatedInfo);
  };

  const showAlert = (title: string, message: string) => {
    // This would normally call a native module for custom alerts
    Alert.alert(title, message);
  };

  const vibrateDevice = () => {
    // This would normally call a native module
    // For example: NativeModules.Vibration.vibrate(1000);
    Alert.alert('Vibration', 'Device would vibrate for 1 second');
  };

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Native Module Integration</Text>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Battery Information</Text>
        {batteryLevel !== null && (
          <Text style={styles.infoLabel}>
            Battery Level: {batteryLevel}%
          </Text>
        )}
        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={getBatteryLevel}
        >
          <Text style={styles.buttonText}>Get Battery Level</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Device Information</Text>
        {Object.keys(deviceInfo).length > 0 ? (
          <View style={styles.deviceInfo}>
            <Text style={styles.infoLabel}>Model: {deviceInfo.model}</Text>
            <Text style={styles.infoLabel}>Brand: {deviceInfo.brand}</Text>
            <Text style={styles.infoLabel}>OS Version: {deviceInfo.systemVersion}</Text>
          </View>
        ) : (
          <Text style={styles.placeholderText}>No device info available</Text>
        )}
        <TouchableOpacity
          style={[styles.button, styles.primaryButton]}
          onPress={getDeviceInfo}
        >
          <Text style={styles.buttonText}>Get Device Info</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Native Actions</Text>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={() => showAlert('Custom Alert', 'This is a custom native alert')}
        >
          <Text style={styles.buttonText}>Show Native Alert</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={vibrateDevice}
        >
          <Text style={styles.buttonText}>Vibrate Device</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.nativeModuleInfo}>
        <Text style={styles.infoLabel}>
          Note: These examples simulate native module calls.
          In a real app, you would create custom native modules
          for iOS (Swift/Objective-C) and Android (Java/Kotlin).
        </Text>
      </View>
    </View>
  );
};

// 5. Event Emitter and Device Events
const EventEmitterExample: React.FC = () => {
  const [events, setEvents] = useState([]);
  const [isListening, setIsListening] = useState(false);
  const eventListenerRef = useRef(null);

  const addEvent = (eventName: string, data: any) => {
    const newEvent = {
      id: Date.now(),
      name: eventName,
      data: JSON.stringify(data),
      timestamp: new Date().toLocaleTimeString(),
    };
    setEvents(prev => [newEvent, ...prev].slice(0, 10));
  };

  const startListening = () => {
    if (!isListening) {
      // Listen to app state changes
      eventListenerRef.current = AppState.addEventListener('change', (nextAppState) => {
        addEvent('App State Change', { state: nextAppState });
      });

      // Listen to memory warnings (iOS only)
      if (Platform.OS === 'ios') {
        // This would normally be implemented as a native module
        console.log('Memory warning listener would be set up here');
      }

      setIsListening(true);
      addEvent('Event Listener Started', { status: 'active' });
    }
  };

  const stopListening = () => {
    if (eventListenerRef.current) {
      eventListenerRef.current.remove();
      eventListenerRef.current = null;
    }
    setIsListening(false);
    addEvent('Event Listener Stopped', { status: 'inactive' });
  };

  const emitCustomEvent = () => {
    // Emit a custom event
    DeviceEventEmitter.emit('customEvent', {
      message: 'Hello from custom event!',
      timestamp: Date.now(),
    });
    addEvent('Custom Event Emitted', { type: 'customEvent' });
  };

  const simulateMemoryWarning = () => {
    if (Platform.OS === 'ios') {
      // Simulate memory warning event
      addEvent('Memory Warning', { level: 'high' });
    } else {
      addEvent('Low Memory', { available: '45MB' });
    }
  };

  useEffect(() => {
    // Listen for custom events
    const customEventSubscription = DeviceEventEmitter.addListener('customEvent', (event) => {
      addEvent('Custom Event Received', event);
    });

    return () => {
      customEventSubscription.remove();
    };
  }, []);

  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>Event Emitter & Device Events</Text>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Event Listener Status</Text>
        <View style={styles.statusContainer}>
          <Text style={styles.statusText}>
            Status: {isListening ? '🟢 Listening' : '🔴 Not Listening'}
          </Text>
          <TouchableOpacity
            style={[
              styles.button,
              isListening ? styles.dangerButton : styles.primaryButton
            ]}
            onPress={isListening ? stopListening : startListening}
          >
            <Text style={styles.buttonText}>
              {isListening ? 'Stop Listening' : 'Start Listening'}
            </Text>
          </TouchableOpacity>
        </View>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Event Actions</Text>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={emitCustomEvent}
        >
          <Text style={styles.buttonText}>Emit Custom Event</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={simulateMemoryWarning}
        >
          <Text style={styles.buttonText}>
            {Platform.OS === 'ios' ? 'Simulate Memory Warning' : 'Simulate Low Memory'}
          </Text>
        </TouchableOpacity>
      </View>

      <View style={styles.section}>
        <Text style={styles.sectionTitle}>Event Log</Text>
        <ScrollView style={styles.eventLog}>
          {events.map((event) => (
            <View key={event.id} style={styles.eventItem}>
              <Text style={styles.eventName}>{event.name}</Text>
              <Text style={styles.eventData}>{event.data}</Text>
              <Text style={styles.eventTime}>{event.timestamp}</Text>
            </View>
          ))}
          {events.length === 0 && (
            <Text style={styles.placeholderText}>No events logged yet</Text>
          )}
        </ScrollView>
      </View>
    </View>
  );
};

// Main App Component
const NativeIntegrationApp: React.FC = () => {
  return (
    <ScrollView style={styles.container}>
      <View style={styles.header}>
        <Text style={styles.headerTitle}>React Native Integration</Text>
        <Text style={styles.headerSubtitle}>Platform-specific features and native APIs</Text>
      </View>

      <PlatformSpecificExample />
      <DeviceAPIsExample />
      <PermissionsExample />
      <NativeModuleExample />
      <EventEmitterExample />
    </ScrollView>
  );
};

// Styles
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f9fa',
  },
  header: {
    padding: 20,
    backgroundColor: '#2c3e50',
    alignItems: 'center',
  },
  headerTitle: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#fff',
    marginBottom: 8,
  },
  headerSubtitle: {
    fontSize: 16,
    color: '#ecf0f1',
    textAlign: 'center',
  },
  card: {
    backgroundColor: '#fff',
    margin: 16,
    padding: 20,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#2c3e50',
    marginBottom: 16,
    textAlign: 'center',
  },
  section: {
    marginBottom: 20,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 12,
  },
  platformInfo: {
    backgroundColor: '#ecf0f1',
    padding: 12,
    borderRadius: 6,
    marginBottom: 16,
  },
  infoLabel: {
    fontSize: 14,
    color: '#2c3e50',
    marginBottom: 4,
  },
  button: {
    paddingVertical: 12,
    paddingHorizontal: 20,
    borderRadius: 6,
    alignItems: 'center',
    marginVertical: 4,
  },
  primaryButton: {
    backgroundColor: '#3498db',
  },
  secondaryButton: {
    backgroundColor: '#95a5a6',
  },
  dangerButton: {
    backgroundColor: '#e74c3c',
  },
  shareButton: {
    backgroundColor: '#27ae60',
    marginLeft: 8,
    flex: 1,
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  platformSpecificUI: {
    marginTop: 16,
  },
  iosUI: {
    backgroundColor: '#f8f9fa',
    padding: 16,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: '#ddd',
  },
  iosLabel: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 12,
    textAlign: 'center',
  },
  iosButton: {
    backgroundColor: '#007AFF',
    padding: 12,
    borderRadius: 8,
    alignItems: 'center',
  },
  iosButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  androidUI: {
    backgroundColor: '#f8f9fa',
    padding: 16,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: '#ddd',
  },
  androidLabel: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 12,
    textAlign: 'center',
  },
  androidButton: {
    backgroundColor: '#4CAF50',
    padding: 12,
    borderRadius: 4,
    alignItems: 'center',
    elevation: 2,
  },
  androidButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  locationInfo: {
    backgroundColor: '#ecf0f1',
    padding: 12,
    borderRadius: 6,
    marginBottom: 12,
  },
  shareContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 12,
  },
  shareInput: {
    flex: 1,
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 6,
    padding: 12,
    fontSize: 16,
    marginRight: 8,
  },
  placeholderText: {
    fontSize: 14,
    color: '#7f8c8d',
    fontStyle: 'italic',
    textAlign: 'center',
    marginVertical: 8,
  },
  statusContainer: {
    alignItems: 'center',
    marginBottom: 16,
  },
  statusText: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 12,
  },
  permissionsStatus: {
    backgroundColor: '#f8f9fa',
    padding: 12,
    borderRadius: 6,
  },
  deviceInfo: {
    backgroundColor: '#ecf0f1',
    padding: 12,
    borderRadius: 6,
  },
  nativeModuleInfo: {
    backgroundColor: '#fff3cd',
    border: 1,
    borderColor: '#ffeaa7',
    borderRadius: 6,
    padding: 12,
    marginTop: 16,
  },
  eventLog: {
    maxHeight: 200,
    backgroundColor: '#f8f9fa',
    borderRadius: 6,
  },
  eventItem: {
    backgroundColor: '#fff',
    padding: 12,
    marginBottom: 4,
    borderRadius: 4,
    borderLeftWidth: 3,
    borderLeftColor: '#3498db',
  },
  eventName: {
    fontSize: 14,
    fontWeight: '600',
    color: '#2c3e50',
    marginBottom: 2,
  },
  eventData: {
    fontSize: 12,
    color: '#7f8c8d',
    marginBottom: 2,
  },
  eventTime: {
    fontSize: 10,
    color: '#95a5a6',
  },
});

export default NativeIntegrationApp;