JAVASCRIPT
Creating a Reusable Error Boundary Component
Build a robust error boundary component in Vue 3 to gracefully catch and display errors from its child components, preventing crashes and improving user experience.
// components/ErrorBoundary.vue
<template>
<template v-if="error">
<div class="error-boundary-feedback">
<h2>Something went wrong!</h2>
<p v-if="showDetailedError">{{ error.message }}</p>
<button @click="resetError">Try again</button>
<p style="color: #666; font-size: 0.9em;">(Error caught by ErrorBoundary)</p>
</div>
</template>
<template v-else>
<slot></slot>
</template>
</template>
<script setup>
import { ref, onErrorCaptured, defineProps, nextTick } from 'vue';
const props = defineProps({
showDetailedError: {
type: Boolean,
default: import.meta.env.DEV, // Show details only in dev mode by default
},
});
const error = ref(null);
// Capture errors from descendants
onErrorCaptured((err, instance, info) => {
error.value = err;
console.error('Error caught by ErrorBoundary:', err, instance, info);
// Return false to stop the error from propagating further up the component chain
return false;
});
async function resetError() {
error.value = null;
// Optional: Force re-render children or navigate away
// Forcing re-render is tricky; often better to let user navigate or fix source.
// Or, if using keys on slot content, change the key to force remount.
// await nextTick();
}
</script>
<style scoped>
.error-boundary-feedback {
border: 2px solid #dc3545;
padding: 20px;
margin: 20px 0;
background-color: #f8d7da;
color: #721c24;
border-radius: 5px;
}
.error-boundary-feedback h2 {
color: #dc3545;
}
.error-boundary-feedback button {
background-color: #dc3545;
color: white;
border: none;
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
margin-top: 10px;
}
</style>
// Usage in a Vue Component:
// components/ProblematicComponent.vue
// <template>
// <button @click="throwError">Throw Error</button>
// </template>
// <script setup>
// function throwError() {
// throw new Error("This is an intentional error from ProblematicComponent!");
// }
// </script>
// App.vue
<template>
<div>
<h1>Application Root</h1>
<p>This part works fine.</p>
<ErrorBoundary>
<ProblematicComponent />
</ErrorBoundary>
<p>This part is also fine, outside the error boundary.</p>
</div>
</template>
<script setup>
import ErrorBoundary from './components/ErrorBoundary.vue';
import ProblematicComponent from './components/ProblematicComponent.vue';
</script>
How it works: This snippet provides a reusable `ErrorBoundary` component for Vue 3. It utilizes the `onErrorCaptured` hook to catch errors that occur within its descendant components. If an error is caught, it displays a fallback UI instead of crashing the entire application, improving the user experience. A `resetError` function allows the user to attempt to re-render the problematic content.