731 words
4 minutes
Error Boundaries - The Security Net for Your App 🛡️

إيه هي Error Boundaries؟ 🤔#

Error Boundaries هي components خاصة في React، بتشتغل كـ”شبكة أمان” لباقي الـcomponents في تطبيقك. بدل ما تطبيقك يقع كله لما يحصل error، الـError Boundary بتمسك الـerror ده وتتعامل معاه بشكل elegant.

ليه محتاجين Error Boundaries؟ 💡#

  • بتمنع التطبيق من الـcrashing الكامل
  • بتحسن تجربة المستخدم (UX)
  • بتسمح لنا نعرض UI بديل (fallback UI)
  • بتساعدنا في الـdebugging

إيه الـerrors اللي بتمسكها Error Boundaries؟ 🎯#

✅ Errors بتمسكها#

  1. Rendering Errors

    • أخطاء في عملية الـrender
    • مشاكل في الـprops أو الـstate
    • Components اللي بترجع undefined
  2. Lifecycle Methods Errors

    • أخطاء في componentDidMount
    • أخطاء في componentDidUpdate
    • أخطاء في componentWillUnmount
  3. Constructor Errors

    • أخطاء في مرحلة الـinitialization
    • مشاكل في الـstate الأولي
  4. Child Components Errors

    • أي أخطاء في الـcomponents اللي جوه الـError Boundary

❌ Errors مش بتمسكها#

  1. Event Handlers

    // لازم نستخدم try-catch هنا
    const handleClick = () => {
      try {
        // your code
      } catch (error) {
        // handle error
      }
    }
    
  2. Asynchronous Code

    • setTimeout
    • requestAnimationFrame
    • async/await
  3. Server Side Rendering

  4. Errors في الـError Boundary نفسها

إزاي نعمل Error Boundary? 🛠️#

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // تحديث الـstate عشان نعرض UI بديل
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // ممكن نعمل log للـerror
    console.error('Error:', error);
    console.error('Error Info:', errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="error-ui">
          <h2>😕 في حاجة غلط حصلت</h2>
          <p>معلش، حاول تاني بعد شوية</p>
        </div>
      );
    }

    return this.props.children;
  }
}

شرح تفصيلي لـ Error Boundary Component 🔍#

1️⃣ تعريف الـClass Component#

class ErrorBoundary extends React.Component {
  // ...
}
  • بنعمل class بيورث من React.Component
  • ده ضروري لأن Error Boundaries لازم تكون class components
  • مينفعش نعملها functional component أو hooks

2️⃣ الـConstructor#

constructor(props) {
  super(props);
  this.state = { hasError: false };
}
  • constructor هو أول حاجة بتتنفذ في الـclass
  • super(props) بتنفذ constructor الـparent class (React.Component)
  • بنعمل state فيه property واحدة hasError
    • false يعني مفيش error
    • true يعني في error حصل

3️⃣ الـError Catching Method الأولى#

static getDerivedStateFromError(error) {
  return { hasError: true };
}
  • ده static method يعني بيتنفذ على الـclass نفسه مش على instance
  • بيتنفذ لما يحصل error في أي component جوه الـError Boundary
  • مهمته الوحيدة إنه يحدث الـstate
  • بيرجع object جديد يعدل الـstate
  • مهم: الmethod دي مينفعش نعمل فيها side effects زي API calls

4️⃣ الـError Catching Method التانية#

componentDidCatch(error, errorInfo) {
  console.error('Error:', error);
  console.error('Error Info:', errorInfo);
}
  • بتتنفذ بعد getDerivedStateFromError
  • بتاخد parameter:
    • error: الـerror نفسه
    • errorInfo: معلومات إضافية عن الـerror وفين حصل
  • مناسبة للـside effects زي:
    • Logging الـerrors
    • إرسال الـerrors لـservice زي Sentry
    • تحديث API أو database

5️⃣ الـRender Method#

render() {
  if (this.state.hasError) {
    return (
      <div className="error-ui">
        <h2>😕 في حاجة غلط حصلت</h2>
        <p>معلش، حاول تاني بعد شوية</p>
      </div>
    );
  }
  return this.props.children;
}
  • بتتنفذ كل ما الـcomponent بيحتاج يتـrender
  • فيها condition:
    • لو hasError بقى true بنعرض رسالة error للمستخدم
    • لو hasError لسه false بنعرض الـchildren العادية
  • this.props.children بيمثل كل الـcomponents اللي محطوطة جوه الـErrorBoundary

مثال للاستخدام 📝#

// طريقة استخدام الـError Boundary
function App() {
  return (
    <ErrorBoundary>
      <div>
        <Header />
        <MainContent />
        <Footer />
      </div>
    </ErrorBoundary>
  );
}

Flow بتاع الـError Boundary 🔄#

  1. Component شغال عادي (hasError: false)
  2. Error يحصل في أي component جواه
  3. getDerivedStateFromError يتنفذ ويخلي hasError: true
  4. componentDidCatch يتنفذ ويعمل log للـerror
  5. render يتنفذ تاني ويعرض رسالة الـerror

نصائح مهمة 💡#

  1. Customization
// إضافة props للتحكم في رسالة الـerror
class ErrorBoundary extends React.Component {
  render() {
    if (this.state.hasError) {
      return this.props.fallback || (
        <div className="error-ui">
          <h2>😕 في حاجة غلط حصلت</h2>
          <p>معلش، حاول تاني بعد شوية</p>
        </div>
      );
    }
    return this.props.children;
  }
}
  1. Reset Function
class ErrorBoundary extends React.Component {
  reset = () => {
    this.setState({ hasError: false });
  }

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h2>😕 في حاجة غلط حصلت</h2>
          <button onClick={this.reset}>حاول تاني</button>
        </div>
      );
    }
    return this.props.children;
  }
}

إزاي نستخدم Error Boundary? 🎨#

function App() {
  return (
    <div>
      <ErrorBoundary>
        <Header />
      </ErrorBoundary>

      <ErrorBoundary>
        <Sidebar />
      </ErrorBoundary>

      <ErrorBoundary>
        <MainContent />
      </ErrorBoundary>
    </div>
  );
}

نصائح مهمة للاستخدام 📝#

  1. التقسيم الصح

    • حط Error Boundary حوالين كل جزء مهم في تطبيقك
    • مش لازم تحط Error Boundary حوالين كل component
  2. ممكن تستخدم مكتبة react-error-boundary

    import { ErrorBoundary } from 'react-error-boundary';
    
    function ErrorFallback({error}) {
      return (
        <div>
          <h2>حصل error 😕</h2>
          <p>{error.message}</p>
        </div>
      );
    }
    
    function App() {
      return (
        <ErrorBoundary FallbackComponent={ErrorFallback}>
          <MyComponent />
        </ErrorBoundary>
      );
    }
    
  3. الـTesting مهم

    it('should show error UI when error occurs', () => {
      const ThrowError = () => { throw new Error('Test Error'); };
      
      render(
        <ErrorBoundary>
          <ThrowError />
        </ErrorBoundary>
      );
    
      expect(screen.getByText('في حاجة غلط حصلت')).toBeInTheDocument();
    });
    

Best Practices 🌟#

  1. Granular Error Boundaries

    • حط Error Boundaries في المستويات المناسبة
    • مش كل حاجة محتاجة Error Boundary
  2. Custom Error UIs

    • اعمل UI مخصص لكل نوع من الـerrors
    • خلي الرسايل واضحة ومفيدة للمستخدم
  3. Error Logging

    • استخدم componentDidCatch للـlogging
    • اربطها بـservice زي Sentry أو LogRocket
  4. Recovery Options

    • إديي المستخدم طريقة يصلح بيها المشكلة
    • زي زرار refresh أو retry

خاتمة 🎯#

Error Boundaries هي أداة قوية في React بتساعدنا نعمل تطبيقات أكتر استقرار ونتعامل مع الـerrors بشكل أفضل. المهم نستخدمها صح ونحط في بالنا إنها مش بتحل كل المشاكل، لكنها بتساعد في تحسين تجربة المستخدم وثبات التطبيق.

Join our whatsapp group here
My Channel here