80 lines
1.8 KiB
TypeScript
80 lines
1.8 KiB
TypeScript
import React, { Component, ReactNode } from 'react';
|
|
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
|
|
type Props = {
|
|
children: ReactNode;
|
|
fallback?: ReactNode;
|
|
};
|
|
|
|
type State = {
|
|
hasError: boolean;
|
|
error: Error | null;
|
|
};
|
|
|
|
export default class ErrorBoundary extends Component<Props, State> {
|
|
state: State = { hasError: false, error: null };
|
|
|
|
static getDerivedStateFromError(error: Error): State {
|
|
return { hasError: true, error };
|
|
}
|
|
|
|
componentDidCatch(error: Error): void {
|
|
const { logError } = require('@/lib/errorLogger');
|
|
logError(error.message, error);
|
|
}
|
|
|
|
handleReset = () => {
|
|
this.setState({ hasError: false, error: null });
|
|
};
|
|
|
|
render() {
|
|
if (this.state.hasError) {
|
|
if (this.props.fallback) return this.props.fallback;
|
|
return (
|
|
<View style={styles.container}>
|
|
<Text style={styles.title}>Terjadi Kesalahan</Text>
|
|
<Text style={styles.message}>
|
|
Silahkan coba lagi beberapa saat lagi atau hubungi admin untuk bantuan.
|
|
</Text>
|
|
<TouchableOpacity style={styles.button} onPress={this.handleReset}>
|
|
<Text style={styles.buttonText}>Coba Lagi</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
);
|
|
}
|
|
return this.props.children;
|
|
}
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
padding: 24,
|
|
backgroundColor: '#f7f7f7',
|
|
},
|
|
title: {
|
|
fontSize: 18,
|
|
fontWeight: '600',
|
|
marginBottom: 8,
|
|
color: '#11181C',
|
|
},
|
|
message: {
|
|
fontSize: 14,
|
|
color: '#707887',
|
|
textAlign: 'center',
|
|
marginBottom: 24,
|
|
},
|
|
button: {
|
|
backgroundColor: '#19345E',
|
|
paddingHorizontal: 24,
|
|
paddingVertical: 12,
|
|
borderRadius: 8,
|
|
},
|
|
buttonText: {
|
|
color: '#fff',
|
|
fontWeight: '600',
|
|
},
|
|
});
|