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 بتمسكها
Rendering Errors
- أخطاء في عملية الـrender
- مشاكل في الـprops أو الـstate
- Components اللي بترجع undefined
Lifecycle Methods Errors
- أخطاء في
componentDidMount
- أخطاء في
componentDidUpdate
- أخطاء في
componentWillUnmount
- أخطاء في
Constructor Errors
- أخطاء في مرحلة الـinitialization
- مشاكل في الـstate الأولي
Child Components Errors
- أي أخطاء في الـcomponents اللي جوه الـError Boundary
❌ Errors مش بتمسكها
Event Handlers
// لازم نستخدم try-catch هنا const handleClick = () => { try { // your code } catch (error) { // handle error } }
Asynchronous Code
setTimeout
requestAnimationFrame
async/await
Server Side Rendering
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
هو أول حاجة بتتنفذ في الـclasssuper(props)
بتنفذ constructor الـparent class (React.Component)- بنعمل state فيه property واحدة
hasError
false
يعني مفيش errortrue
يعني في 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 🔄
- Component شغال عادي (
hasError: false
) - Error يحصل في أي component جواه
getDerivedStateFromError
يتنفذ ويخليhasError: true
componentDidCatch
يتنفذ ويعمل log للـerrorrender
يتنفذ تاني ويعرض رسالة الـerror
نصائح مهمة 💡
- 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;
}
}
- 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>
);
}
نصائح مهمة للاستخدام 📝
التقسيم الصح
- حط Error Boundary حوالين كل جزء مهم في تطبيقك
- مش لازم تحط Error Boundary حوالين كل component
ممكن تستخدم مكتبة
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> ); }
الـ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 🌟
Granular Error Boundaries
- حط Error Boundaries في المستويات المناسبة
- مش كل حاجة محتاجة Error Boundary
Custom Error UIs
- اعمل UI مخصص لكل نوع من الـerrors
- خلي الرسايل واضحة ومفيدة للمستخدم
Error Logging
- استخدم
componentDidCatch
للـlogging - اربطها بـservice زي Sentry أو LogRocket
- استخدم
Recovery Options
- إديي المستخدم طريقة يصلح بيها المشكلة
- زي زرار refresh أو retry
خاتمة 🎯
Error Boundaries هي أداة قوية في React بتساعدنا نعمل تطبيقات أكتر استقرار ونتعامل مع الـerrors بشكل أفضل. المهم نستخدمها صح ونحط في بالنا إنها مش بتحل كل المشاكل، لكنها بتساعد في تحسين تجربة المستخدم وثبات التطبيق.