Error Boundary
Апп ажиллаж байх үед component-д алдаа гарвал React бүх дэлгэцийг цагаан хоосон болгодог — хэрэглэгч юу болсныг ойлгохгүй гацдаг. Error Boundary нь алдааг "барьж" авч, хэрэглэгчид тааламжтай мэдэгдэл харуулдаг. Аппаа мэргэжлийн болгох маш чухал механизм!
Error Boundary гэж юу вэ?
Error Boundary нь child component-уудад гарсан JavaScript алдааг барьж авдаг тусгай component юм. Алдаа гарахад бүх аппыг унагааж дуусахын оронд зөвхөн тухайн хэсгийг "нуран унасан" байдлаар харуулж, бусад хэсгийг ажиллуулсаар байна.
// Error Boundary нь class component байх ёстой — функц component болохгүй
import { Component } from "react";
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
// Алдаа гарахад энэ lifecycle method дуудагдана
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
// Алдааг log хийх боломж
componentDidCatch(error, info) {
console.error("Алдаа гарлаа:", error);
console.error("Component stack:", info.componentStack);
}
render() {
if (this.state.hasError) {
// Алдааны үед харуулах UI
return (
<div style={{ padding: "20px", color: "red", border: "1px solid red" }}>
<h2>Ямар нэг зүйл буруу боллоо 😔</h2>
<p>Хуудсыг дахин ачааллуулна уу.</p>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
Error Boundary нь class component байх ёстой — getDerivedStateFromError ба componentDidCatch lifecycle method-ууд зөвхөн class-д байдаг.
Error Boundary ашиглах нь
Error Boundary-г алдаа гарч болзошгүй component-уудаа боож хэрэглэнэ:
import ErrorBoundary from "./ErrorBoundary";
// Алдаа гаргадаг component — жишээ болгон
function BuggyCounter() {
const [count, setCount] = useState(0);
if (count === 3) {
// 3 дарахад алдаа гарна
throw new Error("Тоолуур гацлаа!");
}
return (
<button onClick={() => setCount(count + 1)}>{count} удаа дарлаа</button>
);
}
export default function App() {
return (
<div>
<h1>Миний апп</h1>
{/* Нэг хэсгийн алдаа нөгөөд нөлөөлөхгүй */}
<ErrorBoundary>
<BuggyCounter />
</ErrorBoundary>
<ErrorBoundary>
<BuggyCounter />
</ErrorBoundary>
<p>Энэ хэсэг хэзээ ч алдаагүй ажиллана.</p>
</div>
);
}
Нэг BuggyCounter-д алдаа гарахад нөгөө нь хэвийн ажиллаж үлдэнэ. Error Boundary нь алдааг тусгаарладаг.
Дахин оролдох товч нэмэх
Хэрэглэгчид алдааны дараа дахин оролдох боломж өгөх нь UX сайжруулдаг:
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
this.handleReset = this.handleReset.bind(this);
}
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, info) {
// Жинхэнэ аппад энд Sentry эсвэл бусад log сервис рүү илгээнэ
console.error(error, info);
}
handleReset() {
this.setState({ hasError: false, error: null });
}
render() {
if (this.state.hasError) {
return (
<div
style={{
padding: "32px",
textAlign: "center",
border: "1px solid #fee2e2",
borderRadius: "8px",
background: "#fef2f2",
}}
>
<h2>Алдаа гарлаа 😕</h2>
<p style={{ color: "#6b7280" }}>
{this.state.error?.message ?? "Тодорхойгүй алдаа"}
</p>
<button
onClick={this.handleReset}
style={{
marginTop: "16px",
padding: "8px 16px",
background: "#3b82f6",
color: "white",
border: "none",
borderRadius: "6px",
cursor: "pointer",
}}
>
Дахин оролдох
</button>
</div>
);
}
return this.props.children;
}
}
Error Boundary юу барьж чадахгүй вэ?
Error Boundary барьж чаддаггүй алдаанууд байдаг — эдгээрийг мэдэх нь чухал:
// ❌ Event handler дахь алдааг барьдаггүй
function BadButton() {
const handleClick = () => {
throw new Error("Click алдаа"); // Error Boundary энийг барихгүй!
};
return <button onClick={handleClick}>Дарах</button>;
}
// ✅ Event handler дахь алдааг try/catch-ээр барина
function GoodButton() {
const [error, setError] = useState(null);
const handleClick = () => {
try {
throw new Error("Click алдаа");
} catch (err) {
setError(err.message);
}
};
return (
<div>
<button onClick={handleClick}>Дарах</button>
{error && <p style={{ color: "red" }}>{error}</p>}
</div>
);
}
Error Boundary нь зөвхөн render, lifecycle method, constructor дахь алдааг барьдаг. Async функц, event handler дахь алдааг тусад нь try/catch-ээр зохицуулах хэрэгтэй.
Дараагийн хичээлд:
Suspense ба lazy loading сурна — том component-уудыг шаардлагатай үед л ачаалах арга. Энэ нь аппын эхний ачааллын хугацааг эрс богиносгодог чухал оновчлол юм.