Skip to content

Commit a499e78

Browse files
refactor(ui): update components to use unified error handler
- Update app/(tabs)/index.tsx with latest changes - Update app/_layout.tsx to use new error handling approach - Update components/ErrorBoundary.tsx to integrate with unified error service
1 parent 3dd079a commit a499e78

3 files changed

Lines changed: 53 additions & 35 deletions

File tree

app/(tabs)/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import BatteryInfo from '@/components/BatteryInfo';
77
import { triggerLocalSampleNotification } from '@/utils/notifications.utils';
88
import { usePushNotifications } from '@/hooks/usePushNotifications';
99
import CustomHeader from '@/components/CustomHeader';
10+
import { simulateAsyncGlobalError, triggerNativeTestException } from '@/services/errorHandler.service';
1011

1112
export default function LocationComponent() {
1213
const { fcmToken } = usePushNotifications();
@@ -79,6 +80,10 @@ export default function LocationComponent() {
7980

8081
<Button title="Get Location" onPress={fetchLocation} />
8182
<Button title="Trigger Sample Notification" onPress={triggerLocalSampleNotification} />
83+
<View style={{ height: 12 }} />
84+
<Button title="JS Crash Test (async)" onPress={() => simulateAsyncGlobalError('Manual JS async crash test')} />
85+
<View style={{ height: 8 }} />
86+
<Button color="#d9534f" title="Native Crash Test" onPress={triggerNativeTestException} />
8287

8388
{/* Link to Login page */}
8489
<View style={{ marginTop: 12 }}>

app/_layout.tsx

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'react-native-reanimated';
88
import { useFonts } from 'expo-font';
99
import FontAwesome from '@expo/vector-icons/FontAwesome';
1010
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
11-
import { View } from 'react-native';
11+
import { View, Button } from 'react-native';
1212
import { StatusBar } from 'expo-status-bar';
1313

1414
import { usePushNotifications, useNotificationObserver } from '@/hooks/usePushNotifications';
@@ -22,45 +22,51 @@ import { AuthProvider } from '@/providers/AuthProvider';
2222
import { SessionProvider } from '@/providers/SessionProvider';
2323
import { useAuth } from '@/hooks/useAuth';
2424

25-
import { setJSExceptionHandler, setNativeExceptionHandler } from 'react-native-exception-handler';
26-
import { safeReport } from '@/services/errorReporting.service';
27-
import { showFatalErrorNotification } from '@/utils/notifications.utils';
25+
import { setJSExceptionHandler, getJSExceptionHandler, setNativeExceptionHandler } from 'react-native-exception-handler';
26+
27+
// Global error handling is centralized in errorHandler.service
2828
// ✅ keep pathing consistent with your alias
29-
import { setupGlobalErrorHandlers } from '@/utils/globalErrorhandler';
29+
//import { setupGlobalErrorHandlers } from '@/services/errorHandler.service';
3030

3131
// Prevent auto-hiding the splash until fonts are loaded
3232
SplashScreen.preventAutoHideAsync().catch(() => {
3333
/* no-op */
3434
});
3535

36-
// --- Global Exception Handler Setup ---
37-
const jsExceptionHandler = (maybeError: unknown, isFatal: boolean) => {
38-
const error = maybeError instanceof Error ? maybeError : new Error(typeof maybeError === 'string' ? maybeError : JSON.stringify(maybeError) || 'Unknown non-Error thrown');
39-
40-
console.log('Caught JS Exception:', error, isFatal);
36+
// Register global handlers at module load (earlier than any component effects)
37+
//setupGlobalErrorHandlers({ baseContext: { tags: { entry: 'root-layout' } } });
4138

42-
safeReport(error, {
43-
isFatal,
44-
errorInfo: { componentStack: 'jsExceptionHandler' },
45-
});
46-
47-
if (isFatal) showFatalErrorNotification(error);
39+
const exceptionhandler = (error: any, isFatal: boolean) => {
40+
console.log('ExceptionHandler called with error: ', error, 'isFatal: ', isFatal);
41+
// your error handler function
4842
};
4943

50-
const nativeExceptionHandler = (exceptionString: string) => {
51-
console.log('Caught Native Exception:', exceptionString);
52-
const error = new Error(`Native Exception: ${exceptionString}`);
44+
const exceptionhandler2 = (exceptionString: string) => {
45+
console.log('Native ExceptionHandler called with exception: ', exceptionString);
46+
// your exception handler code here
47+
};
5348

54-
safeReport(error, {
55-
isFatal: true,
56-
errorInfo: { componentStack: 'nativeExceptionHandler' },
57-
});
49+
const setNativeExceptionHandlerClick = () => {
50+
setNativeExceptionHandler(exceptionhandler2, false, false);
51+
// - exceptionhandler is the exception handler function
52+
// - forceAppQuit is an optional ANDROID specific parameter that defines
53+
// if the app should be force quit on error. default value is true.
54+
// To see usecase check the common issues section.
55+
// - executeDefaultHandler is an optional boolean (both IOS, ANDROID)
56+
// It executes previous exception handlers if set by some other module.
57+
// It will come handy when you use any other crash analytics module along with this one
58+
// Default value is set to false. Set to true if you are using other analytics modules.
59+
};
5860

59-
showFatalErrorNotification(error);
61+
const setJSExceptionHandlerClick = () => {
62+
const originalConsoleError = console.error;
63+
setJSExceptionHandler(exceptionhandler, true);
6064
};
6165

62-
setJSExceptionHandler(jsExceptionHandler, true);
63-
setNativeExceptionHandler(nativeExceptionHandler);
66+
const getJSExceptionHandlerClick = () => {
67+
// getJSExceptionHandler gives the currently set JS exception handler
68+
const currentHandler = getJSExceptionHandler();
69+
};
6470

6571
// --- Component Definition ---
6672
export default function RootLayout() {
@@ -93,6 +99,13 @@ export default function RootLayout() {
9399
<SessionProvider>
94100
<AuthProvider>
95101
<NotificationBootstrap />
102+
<View style={{ flexDirection: 'column', justifyContent: 'space-between' }}>
103+
<Button title="setJSExceptionHandler" onPress={setJSExceptionHandlerClick} />
104+
<Button title="getJSExceptionHandler" onPress={getJSExceptionHandlerClick} />
105+
</View>
106+
<View style={{ flexDirection: 'column', justifyContent: 'space-between' }}>
107+
<Button title="setNativeExceptionHandler" onPress={setNativeExceptionHandlerClick} />
108+
</View>
96109
<RootLayoutNav />
97110
</AuthProvider>
98111
</SessionProvider>
@@ -120,20 +133,20 @@ function RootLayoutNav() {
120133
console.log('User: ', user);
121134
}, [user]);
122135

123-
useEffect(() => {
124-
setupGlobalErrorHandlers();
125-
}, []);
136+
// (global handlers now set at module scope above)
126137

127138
return (
128139
<ErrorBoundary>
129140
<NotificationProvider>
130141
<ThemeProvider value={ForcedDarkTheme}>
131142
<View style={{ flex: 1, backgroundColor: '#000' }}>
132143
<StatusBar style="light" backgroundColor="#000" translucent={false} />
133-
<Stack screenOptions={{
134-
contentStyle: { backgroundColor: '#000' },
135-
headerStyle: { backgroundColor: '#000' },
136-
}}>
144+
<Stack
145+
screenOptions={{
146+
contentStyle: { backgroundColor: '#000' },
147+
headerStyle: { backgroundColor: '#000' },
148+
}}
149+
>
137150
{user ? <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> : <Stack.Screen name="login" options={{ headerShown: false }} />}
138151
<Stack.Screen name="debug" options={{ title: 'Debug' }} />
139152
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />

components/ErrorBoundary.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { Component, ReactNode, ErrorInfo } from "react";
22
import { View, Text, Button, StyleSheet, ScrollView } from "react-native";
3-
import { reportError } from "@/services/errorReporting.service";
3+
import { reportError } from "@/services/errorHandler.service";
44

55
interface Props {
66
children: ReactNode;
@@ -23,7 +23,7 @@ class ErrorBoundary extends Component<Props, State> {
2323

2424
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
2525
// FIX: Calling reportError with the correct 'options' object.
26-
reportError(error, { errorInfo });
26+
reportError(error, { componentStack: 'ErrorBoundary', extra: { errorInfo } });
2727
}
2828

2929
handleResetError = () => {

0 commit comments

Comments
 (0)