Improve error boundary granularity with page and section level boundaries
Implement three-level error boundary strategy: - Top-level (app shell): catches critical failures - Page-level: preserves navigation when page crashes - Section-level: graceful degradation for charts/tables Create new components: - PageErrorBoundary: wraps page routes - SectionErrorBoundary: wraps data-heavy sections Enhance ErrorBoundary with customizable titles, messages, and reload behavior. Apply page boundaries to all route handlers in App.tsx. Apply section boundaries to: - DashboardPage: server status, ban trend, country charts, ban list - JailsPage: jail overview, ban/unban form, IP lookup - MapPage: world map, ban table - ConfigPage: configuration editor - HistoryPage: history table, IP detail view - BlocklistsPage: sources, schedule, import log Update Web-Development.md with error boundary strategy documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,22 +1,3 @@
|
||||
## 13) Config page is over-centralized
|
||||
- Where found:
|
||||
- [frontend/src/pages/ConfigPage.tsx](frontend/src/pages/ConfigPage.tsx)
|
||||
- Why this is needed:
|
||||
- Tab orchestration and UI concerns are too concentrated.
|
||||
- Goal:
|
||||
- Decompose page into focused route/tab controllers.
|
||||
- What to do:
|
||||
- Split tab state/routing logic from rendering components.
|
||||
- Extract domain-specific subcontainers.
|
||||
- Possible traps and issues:
|
||||
- Shared state sync across tabs can regress.
|
||||
- Docs changes needed:
|
||||
- Add config page composition map.
|
||||
- Doc references:
|
||||
- [Docs/Web-Development.md](Docs/Web-Development.md)
|
||||
|
||||
---
|
||||
|
||||
## 14) Error boundary granularity is too coarse
|
||||
- Where found:
|
||||
- [frontend/src/App.tsx](frontend/src/App.tsx)
|
||||
|
||||
@@ -808,15 +808,82 @@ When an API request returns 401 or 403:
|
||||
|
||||
---
|
||||
|
||||
## 12. Error Handling
|
||||
## 12. Error Handling & Resilience
|
||||
|
||||
### API Error Handling
|
||||
|
||||
- Wrap API calls in `try-catch` inside hooks — components should never see raw exceptions.
|
||||
- **All hook catch blocks must use `handleFetchError` rather than directly calling `setError`.** This ensures auth errors (401/403) are routed to the global session-expiry flow instead of displaying confusing error text in the UI. Use the pattern: `handleFetchError(err, setError, "User-friendly fallback message")`.
|
||||
- Display user-friendly error messages — never expose stack traces or raw server responses in the UI.
|
||||
- Use an **error boundary** (`ErrorBoundary` component) at the page level to catch unexpected render errors.
|
||||
- Log errors to the console (or a future logging service) with sufficient context for debugging.
|
||||
- Always handle the **loading**, **error**, and **empty** states for every data-driven component.
|
||||
|
||||
### Error Boundaries — Granular Fallback Strategy
|
||||
|
||||
React error boundaries catch render-time exceptions and allow graceful fallback UI instead of a full white screen crash. BanGUI implements a **three-level error boundary strategy** to balance resilience with UX clarity:
|
||||
|
||||
#### Top-Level Boundary (`<ErrorBoundary>`)
|
||||
- Wraps the entire application in `App.tsx`
|
||||
- Catches critical failures in auth, theming, or routing infrastructure
|
||||
- Shows a full-page fallback with reload button
|
||||
- **Use case:** Rare catastrophic failures; most errors should be caught at lower levels
|
||||
|
||||
#### Page-Level Boundary (`<PageErrorBoundary>`)
|
||||
- Wraps each route in `App.tsx` (Dashboard, Map, Jails, Config, History, Blocklists, etc.)
|
||||
- Catches render errors in page components and their children
|
||||
- Shows a page-level fallback but preserves app shell (sidebar navigation stays functional)
|
||||
- User can still navigate away via the sidebar and retry the page
|
||||
- **Use case:** Page component crashes (component tree errors, unhandled render-time exceptions)
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<Route
|
||||
path="/jails"
|
||||
element={
|
||||
<PageErrorBoundary pageName="Jails">
|
||||
<JailsPage />
|
||||
</PageErrorBoundary>
|
||||
}
|
||||
/>
|
||||
```
|
||||
|
||||
#### Section-Level Boundary (`<SectionErrorBoundary>`)
|
||||
- Wraps individual data-heavy components within a page (charts, tables, forms)
|
||||
- Examples: `BanTrendChart`, `TopCountriesBarChart`, `BanTable`, `JailOverviewSection`
|
||||
- Shows a section-level fallback card but the rest of the page remains functional
|
||||
- User can retry just that section or interact with other sections
|
||||
- **Use case:** Component-specific data fetching errors, rendering issues in risky components
|
||||
|
||||
**Example:**
|
||||
```tsx
|
||||
<div className={styles.section}>
|
||||
<div className={styles.sectionHeader}>
|
||||
<Text as="h2" size={500} weight="semibold">Ban Trend</Text>
|
||||
</div>
|
||||
<SectionErrorBoundary sectionName="Ban Trend Chart">
|
||||
<BanTrendChart timeRange={timeRange} origin={originFilter} source={source} />
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
```
|
||||
|
||||
### When to Use Each Boundary
|
||||
|
||||
- **Page boundaries:** Always wrap page routes in `App.tsx` (`Dashboard`, `Map`, `Jails`, etc.)
|
||||
- **Section boundaries:** Wrap risky components that fetch data or have complex side effects
|
||||
- Data visualizations (charts)
|
||||
- Data tables and lists
|
||||
- Complex forms
|
||||
- Components using external libraries (D3, Canvas, etc.)
|
||||
- **Top-level boundary:** Leave as-is; only modify if auth/routing infrastructure changes
|
||||
|
||||
### Boundary Best Practices
|
||||
|
||||
- Do not over-use boundaries — too many nested boundaries can confuse error UX
|
||||
- Ensure section fallback UI doesn't disrupt page layout (use consistent sizing/spacing)
|
||||
- Provide meaningful error titles and messages (`pageName` and `sectionName` props)
|
||||
- Retry buttons allow users to recover from transient failures without page reload
|
||||
- Consider logging errors via `onError` callback for debugging and monitoring
|
||||
|
||||
---
|
||||
|
||||
## 13. Performance
|
||||
|
||||
Reference in New Issue
Block a user