Add scoped ErrorBoundary to Rules page to contain rendering crashes (#7437)

* [AI] Add scoped ErrorBoundary to Rules page to contain rendering crashes

* [autofix.ci] apply automated fixes

* docs: add release notes for ErrorBoundary PR

* fix(rules): add resetKeys to ErrorBoundary for route navigation reset

In react-error-boundary v6, the boundary does not auto-reset when the
user navigates away and back. Adding resetKeys={[location.pathname]}
ensures the error state clears on route changes.

This contribution was developed with AI assistance (Claude Code).

* fix(rules): show error message in fallback UI and log to console

Addresses reviewer feedback on #7437: surface error.message in the
FeatureErrorFallback so users can copy-paste when reporting issues,
and log the error to the console via useEffect so the error isn't
swallowed by the boundary.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Trevin Chow
2026-04-14 14:06:32 -07:00
committed by GitHub
parent eac26fa4ef
commit c77b4cc220
3 changed files with 76 additions and 2 deletions

View File

@@ -0,0 +1,51 @@
import React, { useEffect } from 'react';
import type { FallbackProps } from 'react-error-boundary';
import { Trans } from 'react-i18next';
import { Button } from '@actual-app/components/button';
import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
export function FeatureErrorFallback({
error,
resetErrorBoundary,
}: FallbackProps) {
useEffect(() => {
console.error(error);
}, [error]);
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
}}
>
<Text style={{ ...styles.mediumText, color: theme.errorText }}>
<Trans>Something went wrong loading this section.</Trans>
</Text>
{error?.message && (
<Text
style={{
...styles.smallText,
fontFamily: 'monospace',
color: theme.errorText,
marginTop: 10,
maxWidth: 600,
textAlign: 'center',
userSelect: 'text',
}}
>
{error.message}
</Text>
)}
<Button onPress={resetErrorBoundary} style={{ marginTop: 15 }}>
<Trans>Try again</Trans>
</Button>
</View>
);
}

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useEffectEvent, useRef } from 'react';
import type { ReactElement } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { useTranslation } from 'react-i18next';
import { Navigate, Route, Routes, useHref, useLocation } from 'react-router';
@@ -23,6 +24,7 @@ import { useDispatch, useSelector } from '#redux';
import { UserAccessPage } from './admin/UserAccess/UserAccessPage';
import { BankSyncStatus } from './BankSyncStatus';
import { CommandBar } from './CommandBar';
import { FeatureErrorFallback } from './FeatureErrorFallback';
import { GlobalKeys } from './GlobalKeys';
import { MobileBankSyncAccountEditPage } from './mobile/banksync/MobileBankSyncAccountEditPage';
import { MobileNavTabs } from './mobile/MobileNavTabs';
@@ -86,6 +88,7 @@ export function FinancesApp() {
const { isNarrowWidth } = useResponsive();
useMetaThemeColor(isNarrowWidth ? theme.mobileViewTheme : undefined);
const location = useLocation();
const dispatch = useDispatch();
const { t } = useTranslation();
@@ -286,11 +289,25 @@ export function FinancesApp() {
/>
<Route
path="/rules"
element={<NarrowAlternate name="Rules" />}
element={
<ErrorBoundary
FallbackComponent={FeatureErrorFallback}
resetKeys={[location.pathname]}
>
<NarrowAlternate name="Rules" />
</ErrorBoundary>
}
/>
<Route
path="/rules/:id"
element={<NarrowAlternate name="RuleEdit" />}
element={
<ErrorBoundary
FallbackComponent={FeatureErrorFallback}
resetKeys={[location.pathname]}
>
<NarrowAlternate name="RuleEdit" />
</ErrorBoundary>
}
/>
<Route
path="/bank-sync"

View File

@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [tmchow]
---
Add scoped ErrorBoundary to Rules page to contain rendering crashes.