Error boundary, içindeki bileşenler render olurken fırlatılan hataları yakalayan ve tüm uygulamayı çökertmek yerine bir yedek arayüz gösteren bir React bileşenidir. Bunun için bir hook olmadığından static getDerivedStateFromError tanımlayan bir class bileşeni olmalıdır. Onu bir kez yazar ve ağacın herhangi bir kısmının etrafına sararsın.
Çocuğun render sırasında hata fırlatması için "Break the profile"a bas.
Profil yedek arayüzle değiştirilir ve sayfanın geri kalanı çalışmaya devam eder. Konsol hatayı iki kez gösterir: React yakalanan her hatayı console.error ile kaydeder ve componentDidCatch onu yeniden kaydeder. "Try again" nedeni (broken) ve boundary'nin hatasını temizler, böylece profil yeniden render olur. reset'ten this.props.onReset();'u kaldır; Try again doğrudan yedek arayüze geri fırlatır, çünkü hiçbir şey nedeni düzeltmedi.
Class nasıl çalışır
İki metot bir class'ı bir error boundary yapar:
static getDerivedStateFromError(error), bir çocuk hata fırlattıktan hemen sonra render sırasında çalışır. Boundary'yi yedek arayüzüne geçiren state güncellemesini döndürür. Saf olmalıdır: kayıt yok, istek yok.componentDidCatch(error, info), yedek arayüz ekrandayken çalışır. Onu hatayı bir raporlama servisine göndermek gibi yan etkiler için kullan.info.componentStack, hata fırlatan bileşeni ve üstündeki bileşenleri listeler.
class ErrorBoundary extends Component {
state = { error: null };
static getDerivedStateFromError(error) {
return { error }; // switch to the fallback
}
componentDidCatch(error, info) {
reportError(error, info.componentStack); // your logging service
}
render() {
if (this.state.error) return this.props.fallback;
return this.props.children;
}
}
Hook karşılığı yoktur, bu yüzden yalnızca fonksiyon bileşenleriyle yazılmış bir uygulamanın bile bu tek class'a ihtiyacı vardır. Class sözdizimi sana yeniyse class bileşenleri sayfası onu anlatıyor.
Bir boundary neyi yakalar, neyi yakalamaz
Bir boundary, React içindeki bileşenler üzerinde çalışırken olan hataları yakalar:
- render (bir fonksiyon bileşeninin gövdesi, bir class'ın
render'ı), - çocuk class bileşenlerinin yaşam döngüsü metotları ve constructor'ları,
- efektler (
useEffect,useLayoutEffect) ve ref callback'leri, - use ile okunan reddedilmiş bir promise ve React 19'da bir form action'ının ya da
useTransition'dan gelenstartTransition'a aktarılan bir fonksiyonun fırlattığı hata.
Yakalamadıkları:
- olay işleyicilerindeki hatalar,
- kendin başlattığın async kod:
setTimeout,.then()callback'leri, bir olay işleyicisindeki birawait, - boundary'nin kendi
render'ındaki hatalar (onları bir üstteki boundary yakalar), - sunucu tarafı render sırasındaki hatalar.
Olay işleyicileri render'ı bozmadıkları için dışarıda bırakılır. Ekran hâlâ geçerli bir durumdadır, bu yüzden işleyicideki bir try/catch yeterlidir. Boundary'nin görünmesini gerçekten istiyorsan hatayı state'te sakla ve bir sonraki render'da fırlat:
İlk düğme düğmeleri ekranda bırakır ve konsola yalnızca yakalanmamış bir hata yazdırır. İkincisi reddedilmeyi yakalar, saklar ve boundary devralır.
Boundary'ler nereye konmalı
Tüm uygulamanın etrafındaki tek bir boundary beyaz ekranı durdurur, ama o zaman herhangi bir küçük hata her şeyin yerini alır. Boundary'leri bağımsız olarak başarısız olabilen parçaların etrafına koy: bir kenar çubuğu widget'ı, bir grafik, her rota. Bir başarısızlık o zaman kullanıcıya sayfaya değil, bir panele mal olur.
Yalnızca Stocks paneli yedek arayüzünü gösterir. İki widget'ı tek bir <ErrorBoundary>'ye taşı; çalışan Weather paneli de onunla birlikte kaybolur.
Hiç boundary olmadan, bir render hatası yakalanmadığında React tüm ağacı ekrandan kaldırır. Boş bir sayfa, yanlış veri gösteren bozuk bir sayfadan daha güvenlidir, ama kullanıcılar onu bir çökme olarak okur.
react-error-boundary kütüphanesi
react-error-boundary paketi class'ı senin için sarar ve sıfırlama yardımcıları ekler. Bu editörde mevcut değil, bu yüzden burada statik bir blokta:
import { ErrorBoundary, useErrorBoundary } from 'react-error-boundary';
function Fallback({ error, resetErrorBoundary }) {
return (
<div role="alert">
<p>Something went wrong: {error.message}</p>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
);
}
<ErrorBoundary FallbackComponent={Fallback} onReset={() => refetch()} resetKeys={[userId]}>
<Profile userId={userId} />
</ErrorBoundary>;
// Inside a child: hand an async error to the boundary
const { showBoundary } = useErrorBoundary();
fetchData().catch(showBoundary);
resetKeys, listelenen herhangi bir değer değiştiğinde boundary'yi sıfırlar ve showBoundary, önceki örnekteki "sakla ve fırlat" numarasını yapar.
React 19'da hataları raporlamak
React 19 hataları yeni bir şekilde raporlar. Bir boundary tarafından yakalanan hatalar bir kez console.error ile kaydedilir, yakalanmamış hatalar ise window.reportError'a gider. Onları kendi servisine göndermek için createRoot'a seçenekler aktar. Her seçenek eşleşen varsayılan kaydın yerini alır:
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'), {
onCaughtError(error, errorInfo) {
// an error boundary caught it
logToService('caught', error, errorInfo.componentStack);
},
onUncaughtError(error, errorInfo) {
// no boundary caught it, and React removed the tree
logToService('uncaught', error, errorInfo.componentStack);
},
onRecoverableError(error, errorInfo) {
// React recovered by itself, for example after a hydration mismatch
logToService('recovered', error, errorInfo.componentStack);
},
});
root.render(<App />);
onRecoverableError, React'in senin yardımın olmadan düzelttiği hatalar içindir; örneğin bir hydration uyuşmazlığı ya da React yeniden denediğinde kaybolan bir render hatası. hydrateRoot aynı üç seçeneği alır.
Yaygın hatalar
Boundary'yi hata fırlatan bileşenin içine koymak. Bir boundary yalnızca çocuklarından gelen hataları yakalar. Profile kendi JSX'inin etrafında <ErrorBoundary> render edip sonra kendi gövdesinde hata fırlatırsa, hata onu geçip bir üstteki boundary'ye gider. Bileşeni ebeveyninden sar.
getDerivedStateFromError içinde yan etkiler. Render sırasında çalışır ve birden fazla kez çalışabilir, bu yüzden onu state döndürmekle sınırla. Kayıt tutmak componentDidCatch'e ya da kökün onCaughtError'ına aittir.
Hiçbir şeyi düzeltmeyen bir sıfırlama. Boundary'nin hatasını temizlemek aynı çocukları aynı props ile render eder. Yeniden hata fırlatırlarsa kullanıcı yedek arayüze geri döner. Önce hataya neyin neden olduğunu değiştir (yeniden veri çek, hatalı girdiyi temizle, key'i değiştir), sonra hatayı temizle; ilk örnek bunu onReset ile yapıyor.
Tüm uygulama için tek bir boundary ve başka hiçbir şey. Boş sayfayı önler ama her küçük başarısızlığı tam sayfalık bir hataya dönüştürür. Özelliklerin etrafına boundary'ler ekle ve en üst düzeydekini son çare olarak tut.
Hatayı senden gizleyen yedek arayüzler. Dostça bir mesaj kullanıcılar için doğrudur, ama hatanın yine de kayıtlarına ulaştığından emin ol. React 19 yakalanan hataları varsayılan olarak konsola kaydeder; production'da o konsol kullanıcının konsoludur, bu yüzden hataları componentDidCatch'ten ya da onCaughtError'dan bir servise gönder.
Error boundary'ler <Suspense> ile doğal olarak eşleşir: Suspense "henüz hazır değil"i, boundary ise "başarısız oldu"yu ele alır. use örneklerindeki gibi boundary'yi Suspense'in dışına koy, böylece tek bir bileşen yüklemeyi, başarıyı ve başarısızlığı kapsar.
Sıkça Sorulan Sorular
React'te error boundary nedir?
İçindeki herhangi bir bileşen render olurken fırlatılan JavaScript hatalarını yakalayan ve bunun yerine bir yedek arayüz render eden bir bileşendir. Bir tane olmadan render sırasındaki bir hata tüm uygulamayı ekrandan kaldırır.
Error boundary'ler için bir hook var mı?
Hayır. Bir error boundary, static getDerivedStateFromError (ve isteğe bağlı olarak componentDidCatch) içeren bir class bileşeni olmalıdır. Onu bir kez yazar ve fonksiyon bileşenlerinden diğer her bileşen gibi kullanırsın ya da class'ı senin için saran react-error-boundary'yi kurarsın.
Error boundary'ler olay işleyicilerindeki hataları yakalar mı?
Hayır. Olay işleyicileri render'ın dışında çalışır, bu yüzden React'in toparlanmak için bir boundary'ye ihtiyacı yoktur. İşleyicide try/catch kullan; boundary'nin görünmesini istiyorsan hatayı state'te sakla ve render sırasında fırlat.
Error boundary'ler async hataları yakalar mı?
Kendin başlattığın setTimeout, promise callback'leri ya da fetch().then()'den gelenleri yakalamaz. use ile okunan reddedilmiş bir promise'i ve React 19'da bir form action'ının ya da useTransition'dan gelen startTransition'a aktarılan bir fonksiyonun içinde fırlatılan hatayı yakalar.
Bir error boundary nasıl sıfırlanır?
Hataya neden olan şeyi düzelttikten sonra, genellikle yedek arayüzdeki bir Try again düğmesinden, hata state'ini temizle. Boundary'nin key'ini değiştirmek de onu sıfırlar, çünkü React yeni bir örnek mount eder.