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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs