feat(mobile): add ErrorBoundary for render-error fallback

This commit is contained in:
byGalax
2026-05-13 23:34:46 +02:00
parent 1bf4f4bb83
commit bb7aeec345
+68
View File
@@ -0,0 +1,68 @@
import React from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
// Catch render errors anywhere below this boundary and show a readable
// fallback. Without it, a thrown error during render produces a white
// screen on TestFlight / production builds with no way for the user to
// recover short of force-closing the app. Mounted once at the top of
// app/_layout.tsx so it wraps every screen.
interface Props {
children: React.ReactNode;
}
interface State {
error: Error | null;
}
export class ErrorBoundary extends React.Component<Props, State> {
state: State = { error: null };
static getDerivedStateFromError(error: Error): State {
return { error };
}
componentDidCatch(error: Error, info: React.ErrorInfo): void {
// Bubble to Metro/console in dev so the redbox still shows; in prod
// builds this is the only place an exception trace surfaces.
console.error('[ErrorBoundary] caught render error', error, info.componentStack);
}
reset = (): void => {
this.setState({ error: null });
};
render(): React.ReactNode {
if (this.state.error) {
return (
<View style={styles.container}>
<Text style={styles.title}>Etwas ist schiefgelaufen</Text>
<Text style={styles.message}>{this.state.error.message}</Text>
<Pressable style={styles.button} onPress={this.reset}>
<Text style={styles.buttonText}>Erneut versuchen</Text>
</Pressable>
</View>
);
}
return this.props.children;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#0b0b0f',
padding: 24,
},
title: { color: '#fff', fontSize: 22, fontWeight: '600', marginBottom: 8 },
message: { color: '#9ca3af', textAlign: 'center', marginBottom: 24 },
button: {
backgroundColor: '#5865f2',
paddingHorizontal: 20,
paddingVertical: 12,
borderRadius: 10,
},
buttonText: { color: '#fff', fontWeight: '600' },
});