Platform
    • Memoization
    • Error Boundaries
Projects
  • API Connections & Tools
  1. Documentation
  2. Documentation

Error Boundary

Изоляция ошибок пользовательского интерфейса и обеспечение стабильности приложения.

Стандарты изоляции ошибок

Принципы: Изоляция сбоев позволяет приложению продолжать работу даже при падении отдельного виджета или фичи.

Иерархическое дерево надежности

Когда использовать

  • Изоляция падений:

    Виджеты, внешние компоненты, сложные UI-блоки, Lazy-loaded компоненты и интеграции (чаты, карты).

  • Границы слоев:

    Page-level (вся страница) и Feature-level (отдельный блок: корзина, чат, аналитика).

  • Динамический код:

    Когда код может быть нестабилен или подключается сторонний модуль.

01Реализация ErrorBoundary

Базовый класс для перехвата ошибок:

shared/ui/error-boundary/error-boundary.tsx
1"use client"; 2 3import React, { Component, ErrorInfo, ReactNode } from "react"; 4 5interface Props { 6 children?: ReactNode; 7 fallback?: ReactNode; 8} 9 10interface State { 11 hasError: boolean; 12 error: Error | null; 13} 14 15export class ErrorBoundary extends Component<Props, State> { 16 public state: State = { 17 hasError: false, 18 error: null 19 }; 20 21 public static getDerivedStateFromError(error: Error): State { 22 return { hasError: true, error }; 23 } 24 25 public componentDidCatch(error: Error, errorInfo: ErrorInfo) { 26 console.error("ErrorBoundary caught an error:", error, errorInfo); 27 } 28 29 public render() { 30 if (this.state.hasError) { 31 return ( 32 this.props.fallback || ( 33 <div className="p-4 rounded-lg flex flex-col items-start gap-2 border border-destructive/50 bg-destructive/10 text-destructive font-mono text-sm max-w-full overflow-x-auto"> 34 <span className="font-bold flex items-center gap-2"> 35 ⚠️ An error occurred while rendering this component. 36 </span> 37 <details className="mt-2 w-full"> 38 <summary className="cursor-pointer font-semibold opacity-80 hover:opacity-100"> 39 {this.state.error?.message || "Error"} 40 </summary> 41 <pre className="mt-2 text-xs opacity-70 whitespace-pre-wrap"> 42 {this.state.error?.stack} 43 </pre> 44 </details> 45 </div> 46 ) 47 ); 48 } 49 50 return this.props.children; 51 } 52}

02Реализация withErrorBoundary

HOC для оборачивания компонентов:

shared/ui/error-boundary/with-error-boundary.tsx
1import React, { ComponentType } from "react"; 2import { ErrorBoundary } from "./error-boundary"; 3 4export function withErrorBoundary<P extends object>( 5 Component: ComponentType<P>, 6 fallback?: React.ReactNode 7) { 8 return function WithErrorBoundary(props: P) { 9 return ( 10 <ErrorBoundary fallback={fallback}> 11 <Component {...props} /> 12 </ErrorBoundary> 13 ); 14 }; 15}

03Пример использования HOC

Практический пример изоляции фичи с помощью withErrorBoundary. Обратите внимание на то, как HOC предотвращает "белый экран" при ошибках в нестабильной логике рендеринга дочерних компонентов.

HOC Usage Example
1import { withErrorBoundary } from "@/shared/ui"; 2 3function UserProfileWidget({ userId }: { userId: string }) { 4 const { data, isLoading } = useGetUserProfileQuery(userId); 5 6 if (isLoading) return <SkeletonProfile />; 7 8 const formattedStats = data.stats.map(stat => ({ 9 ...stat, 10 value: (stat.raw / stat.total) * 100 11 })); 12 13 return ( 14 <div className="flex flex-col gap-4"> 15 <UserProfileAvatar user={data.user} /> 16 <UserProfileStats stats={formattedStats} /> 17 </div> 18 ); 19} 20 21export const UserProfile = withErrorBoundary(UserProfileWidget, <UserProfileErrorUI />);