JAVASCRIPT
Implement Component Error Boundaries with onErrorCaptured in Vue 3
Learn how to gracefully handle runtime errors within your Vue 3 component tree using the `onErrorCaptured` lifecycle hook, creating robust and resilient error boundaries.
// ErrorBoundary.vue
<template>
<div class="error-boundary">
<div v-if="error">
<p>Something went wrong:</p>
<details style="white-space: pre-wrap;">{{ error }}</details>
<button @click="resetError">Try again</button>
</div>
<slot v-else></slot>
</div>
</template>
<script setup>
import { ref, onErrorCaptured } from 'vue';
const error = ref(null);
onErrorCaptured((err, instance, info) => {
error.value = err.message + '
' + info;
console.error('Caught error in ErrorBoundary:', err, instance, info);
// Return false to stop the error from propagating further up the component tree
return false;
});
const resetError = () => {
error.value = null;
};
</script>
<style scoped>
.error-boundary {
padding: 1em;
border: 1px solid red;
background-color: #ffeaea;
margin: 1em 0;
}
</style>
// MalfunctioningComponent.vue
<template>
<div>
<button @click="throwError">Click to Throw Error</button>
<p v-if="counter % 2 === 0">Even count: {{ counter }}</p>
<p v-else>Odd count: {{ counter }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const counter = ref(0);
const throwError = () => {
// Simulate an error
throw new Error('This is a simulated component error!');
};
setInterval(() => {
counter.value++;
}, 2000);
</script>
// App.vue
<template>
<h1>App Root</h1>
<ErrorBoundary>
<MalfunctioningComponent />
</ErrorBoundary>
<ErrorBoundary>
<p>Another safe area</p>
</ErrorBoundary>
</template>
<script setup>
import ErrorBoundary from './ErrorBoundary.vue';
import MalfunctioningComponent from './MalfunctioningComponent.vue';
</script>
How it works: The `onErrorCaptured` hook in Vue 3 provides a powerful mechanism to capture errors that occur in child components within the component tree. This snippet demonstrates creating an `ErrorBoundary` component that utilizes `onErrorCaptured` to catch errors originating from its slot content. When an error is caught, it displays a fallback UI with error details instead of crashing the entire application, making the application more robust. Returning `false` from `onErrorCaptured` prevents the error from propagating further up the component chain.