Troubleshooting
Guide de résolution des problèmes courants lors du développement et de l'utilisation de l'application mobile.
Common Issues
Problèmes fréquemment rencontrés et leurs solutions.
L'app ne démarre pas
Vérifiez que les dépendances sont installées avec `pnpm install` et que Metro est bien lancé.
Erreur de connexion API
Vérifiez que l'URL de l'API est correcte dans `.env.local` et que le backend est accessible.
Build iOS échoue
Exécutez `cd ios && pod install` puis `pnpm expo prebuild --clean`.
Biometric ne fonctionne pas
Vérifiez que Face ID/Touch ID est configuré dans les paramètres du simulateur.
Build Errors
Erreurs de compilation et de build.
CocoaPods Issues (iOS)
# Clean and reinstall pods
cd ios
rm -rf Pods Podfile.lock
pod cache clean --all
pod install --repo-update
cd ..
# If still failing, reset native projects
npx expo prebuild --clean
# Clear watchman cache
watchman watch-del-allGradle Issues (Android)
# Clean Android build
cd android
./gradlew clean
cd ..
# Clear all caches
rm -rf android/.gradle
rm -rf android/app/build
# Rebuild
pnpm expo prebuild --clean --platform androidMetro Bundler Issues
# Clear Metro cache
pnpm start --clear
# Or manually clear all caches
rm -rf node_modules/.cache
rm -rf .expo
watchman watch-del-all
# Reset Metro and start fresh
npx expo start -cRuntime Errors
Erreurs courantes lors de l'exécution.
Navigation Context Error
Error: Couldn't find the prevent remove context
Ce problème survient quand des hooks React s'exécutent avant que le contexte de navigation soit disponible.
// BAD - hooks in same component as Stack
export default function RootLayout() {
const { initialize } = useAuthStore(); // ❌ Causes error
useEffect(() => { initialize(); }, []);
return <Stack />; // Error here
}
// GOOD - hooks in child component
function RootLayoutNav() {
const { initialize } = useAuthStore(); // ✅ Works
useEffect(() => { initialize(); }, []);
return <Stack />;
}
export default function RootLayout() {
return (
<Providers>
<RootLayoutNav /> {/* Hooks run after context is ready */}
</Providers>
);
}SecureStore Access Error
// SecureStore can fail on some devices
async function safeGetSecureItem(key: string): Promise<string | null> {
try {
return await SecureStore.getItemAsync(key);
} catch (error) {
console.error('SecureStore error:', error);
// Fallback to AsyncStorage for non-critical data
if (!isCriticalKey(key)) {
return await AsyncStorage.getItem(key);
}
// For critical data, force re-authentication
return null;
}
}
// Check if device supports SecureStore
async function checkSecureStoreSupport(): Promise<boolean> {
try {
const testKey = '__secure_store_test__';
await SecureStore.setItemAsync(testKey, 'test');
await SecureStore.deleteItemAsync(testKey);
return true;
} catch {
return false;
}
}Network Issues
Problèmes de connexion réseau et API.
API Connection Failed
// Check API connectivity
async function debugAPIConnection() {
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
console.log('API URL:', apiUrl);
console.log('Network state:', await NetInfo.fetch());
try {
const response = await fetch(`${apiUrl}/health`);
console.log('Health check:', response.status);
} catch (error) {
console.error('Connection failed:', error);
// Common issues:
// 1. localhost doesn't work on device - use IP address
// 2. HTTP blocked on iOS - use HTTPS or configure ATS
// 3. Android cleartext traffic blocked - add to AndroidManifest
}
}
// For development on physical device
// Replace localhost with your machine's IP:
// EXPO_PUBLIC_API_URL=http://192.168.1.100:3000/apiCertificate/SSL Errors
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- Development only: allow cleartext for localhost -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
<!-- Production: strict certificate validation -->
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.yanipay.com</domain>
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</domain-config>
</network-security-config>Performance
Optimisations et résolution des problèmes de performance.
Slow List Rendering
// BAD - re-renders entire list
<FlatList
data={transactions}
renderItem={({ item }) => <TransactionItem transaction={item} />}
/>
// GOOD - optimized with proper keys and memoization
import { memo, useCallback } from 'react';
const MemoizedTransactionItem = memo(TransactionItem);
function TransactionList() {
const renderItem = useCallback(
({ item }) => <MemoizedTransactionItem transaction={item} />,
[]
);
const keyExtractor = useCallback((item) => item.id, []);
return (
<FlatList
data={transactions}
renderItem={renderItem}
keyExtractor={keyExtractor}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={5}
initialNumToRender={10}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
);
}Memory Leaks
// BAD - memory leak with subscriptions
useEffect(() => {
const unsubscribe = someStore.subscribe(callback);
// Missing cleanup!
}, []);
// GOOD - proper cleanup
useEffect(() => {
const unsubscribe = someStore.subscribe(callback);
return () => unsubscribe(); // Cleanup on unmount
}, []);
// BAD - async operation without abort
useEffect(() => {
fetchData().then(setData);
}, []);
// GOOD - with abort controller
useEffect(() => {
const controller = new AbortController();
fetchData({ signal: controller.signal })
.then(setData)
.catch(error => {
if (!controller.signal.aborted) {
console.error(error);
}
});
return () => controller.abort();
}, []);Debugging Tips
Techniques de debugging avancées.
React Native Debugger
# Install React Native Debugger (macOS)
brew install --cask react-native-debugger
# Or use Flipper
brew install --cask flipper
# Start with debugging enabled
pnpm start
# Then press 'j' to open debugger
# Or shake device and select "Debug with Chrome"Network Inspection
// Add request/response logging in development
if (__DEV__) {
apiClient.interceptors.request.use(request => {
console.log('🌐 Request:', request.method?.toUpperCase(), request.url);
console.log('📤 Data:', JSON.stringify(request.data, null, 2));
return request;
});
apiClient.interceptors.response.use(
response => {
console.log('✅ Response:', response.status, response.config.url);
return response;
},
error => {
console.log('❌ Error:', error.response?.status, error.config?.url);
console.log('📥 Error data:', error.response?.data);
return Promise.reject(error);
}
);
}Expo Doctor
# Run Expo diagnostics
pnpm expo doctor
# Check for dependency issues
pnpm expo install --check
# Fix incompatible dependencies
pnpm expo install --fix
# View detailed logs
EXPO_DEBUG=true pnpm start