JAVASCRIPT
Implement Component-Level Error Boundaries with `onErrorCaptured`
Learn to catch and handle errors within child components in Vue 3 using the `onErrorCaptured` lifecycle hook to create robust error boundaries.
// components/ErrorBoundary.vue
<template>
<div class="error-boundary">
<template v-if="error">
<div class="error-display">
<h2>Something went wrong!</h2>
<p>{{ error.message }}</p>
<button @click="resetError">Try again</button>
<details style="white-space: pre-wrap;">{{ error.stack }}</details>
</div>
</template>
<template v-else>
<slot></slot>
</template>
</div>
</template>
<script setup>
import { ref, onErrorCaptured } from 'vue';
const error = ref(null);
// onErrorCaptured catches errors from any descendant component
onErrorCaptured((err, instance, info) => {
error.value = err;
console.error('Caught error in ErrorBoundary:', err, instance, info);
// Return false to stop the error from propagating further up the component tree
// or to the global error handler.
return true; // Return true to prevent error from propagating further
});
const resetError = () => {
error.value = null;
};
</script>
<style scoped>
.error-boundary {
border: 1px dashed #ccc;
padding: 15px;
margin: 10px 0;
}
.error-display {
background-color: #ffebee;
color: #d32f2f;
padding: 10px;
border-radius: 4px;
}
.error-display h2 {
color: #d32f2f;
margin-top: 0;
}
</style>
// components/BuggyComponent.vue
<template>
<div>
<p>This component sometimes throws an error.</p>
<button @click="throwError">Trigger Error</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
const throwError = () => {
count.value++;
if (count.value % 2 !== 0) { // Throw error on odd clicks
throw new Error('An intentional error occurred in BuggyComponent!');
}
};
</script>
// App.vue (Example Usage)
<template>
<div>
<h1>App Component</h1>
<ErrorBoundary>
<BuggyComponent />
</ErrorBoundary>
<p>This content remains visible even if BuggyComponent fails.</p>
<hr>
<ErrorBoundary>
<template #default>
<p>Another section with a different error boundary.</p>
<BuggyComponent />
</template>
</ErrorBoundary>
</div>
</template>
<script setup>
import ErrorBoundary from './components/ErrorBoundary.vue';
import BuggyComponent from './components/BuggyComponent.vue';
</script>
How it works: This snippet demonstrates how to create a component-level error boundary in Vue 3 using the `onErrorCaptured` lifecycle hook. When placed around child components, `ErrorBoundary.vue` will catch errors that occur within its slots. Upon an error, it prevents the error from propagating further, displays a fallback UI with error details, and allows for resetting the error state. This enhances application resilience by isolating faulty parts of the UI and preventing entire application crashes.