Files
wifi-densepose/mobile/src/components/ErrorBoundary.tsx
Yossi Elkrief 779bf8ff43 feat: Phase 3 — services, stores, navigation, design system
Services: ws.service, api.service, simulation.service, rssi.service (android+ios)
Stores: poseStore, settingsStore, matStore (Zustand)
Types: sensing, mat, api, navigation
Hooks: usePoseStream, useRssiScanner, useServerReachability
Theme: colors, typography, spacing, ThemeContext
Navigation: MainTabs (5 tabs), RootNavigator, types
Components: GaugeArc, SparklineChart, OccupancyGrid, StatusDot, ConnectionBanner, SignalBar, +more
Utils: ringBuffer, colorMap, formatters, urlValidator

Verified: tsc 0 errors, jest passes
2026-03-02 12:53:45 +02:00

67 lines
1.6 KiB
TypeScript

import { Component, ErrorInfo, ReactNode } from 'react';
import { Button, StyleSheet, View } from 'react-native';
import { ThemedText } from './ThemedText';
import { ThemedView } from './ThemedView';
type ErrorBoundaryProps = {
children: ReactNode;
};
type ErrorBoundaryState = {
hasError: boolean;
error?: Error;
};
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('ErrorBoundary caught an error', error, errorInfo);
}
handleRetry = () => {
this.setState({ hasError: false, error: undefined });
};
render() {
if (this.state.hasError) {
return (
<ThemedView style={styles.container}>
<ThemedText preset="displayMd">Something went wrong</ThemedText>
<ThemedText preset="bodySm" style={styles.message}>
{this.state.error?.message ?? 'An unexpected error occurred.'}
</ThemedText>
<View style={styles.buttonWrap}>
<Button title="Retry" onPress={this.handleRetry} />
</View>
</ThemedView>
);
}
return this.props.children;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
gap: 12,
},
message: {
textAlign: 'center',
},
buttonWrap: {
marginTop: 8,
},
});