A reusable error boundary component for catching JavaScript errors and displaying fallback UIs.

Overview

vue-error-boundary

NPM version

A reusable error boundary component for catching JavaScript errors and displaying fallback UIs.

The ErrorBoundary component is based on React's example component.

Requires Vue3

Install

yarn add vue-error-boundary

npm i vue-error-boundary --save

Usage

To use this component simply wrap any other component which may throw an Error. Errors thrown in child components will automatically bubble up to the VErrorBoundary component.

<VErrorBoundary>
  <ImUnstable />
VErrorBoundary>

If you are using it inside a v-for, ensure to set the stop-propagation prop on your VErrorBoundary component.

...
">
<div v-for="...">
  <VErrorBoundary stop-propagation>
    ...
  VErrorBoundary>
div>

Props

Attribute Description Type Required Default
fall-back Fallback component to render in case of error. Component false DefaultFallback
on-error Callback function to perform on error. Function false null
params Props to pass to your fall back component. Object false {}
stop-propagation Stop propagation of errors to other errorCaptured hooks. boolean false false

Scoped Slots

Property Description Type
error The error Error
hasError Whether an error occurred. boolean
info Information on where the error was captured string

How to Use

Fallback UI via fall-back

We can provide a fallback UI to display via the fall-back prop. It simply takes a Vue component to render.

Basic Example

">
<template>
  <VErrorBoundary :fall-back="productError">
    <ProductCard ... />
  VErrorBoundary>
template>

<script>
import ProductErrorCard from '...'

export default {
  // ...
  data () {
    return {
      productError: ProductErrorCard
    }
  }
}
script>

With Props

You can pass props to your fallback component through the params prop. params expects an object containing the data you wish to pass.

">
<template>
  <ul class="contact-list">
    <template v-for="contact in contacts">
      <VErrorBoundary :key="contact.id" 
                      :fall-back="fallBack" 
                      :params="{ id: contact.id }">
        <app-contact :contact="contact" />
      VErrorBoundary>
    template>
  ul>
template>

<script>
import MyCustomFallbackComponent from '...'

export default {
  data: () => ({
    fallBack: MyCustomFallbackComponent,
    contacts: [...]
  })
}
script>

Then in your custom fallback component:

<template>
  <div>
    Could not render - {{ id }}
  div>
template>

<script>
export default {
  props: ['id'],
}
script>

Furthermore, we can directly access the contents of the VErrorBoundary component's errorCaptured hook either through a callback or Vue's emit.

Scoped Slots

If you do not wish to use a fallback component you can alternatively utilize scoped slots to present data in your current template.

Basic Example

No error occurred.
Message to appear if error occurred.
">
<VErrorBoundary>
  <template #boundary="{ hasError }">
    <div v-if="!hasError">No error occurred.div>
    <div v-else>Message to appear if error occurred.div>
  template>
VErrorBoundary>

Events

Callbacks via on-error

The VErrorBoundary can receive a callback function through the on-error prop.

... ">
<template>
  <VErrorBoundary @error-captured="handleError">...VErrorBoundary>
template>

<script>
// ...
methods: {
  handleError (err, vm, info) {
    // do something
  }
}
// ...
script>

Stop Propagation

The errorCaptured hook will continue to propagate errors up the component tree unless it returns false. Doing so will stop any additional errorCaptured hooks to execute and the global errorHandler from being invoked for the error. To do this we can use the stop-propagation prop.

<VErrorBoundary stop-propagation>
  ...
VErrorBoundary>

Contributors

wallyjue

Comments
  • Component no longer works

    Component no longer works

    Hi, i came across this component when looking into error handling in vue. I followed the documentations to setup a project and test its functionality and I believe that the component no longer works.

    Please see this CodeSanbox

    And this StackOverflow for further information

    opened by Gabby995 6
  • Vue 3 support

    Vue 3 support

    Hi, does this work with Vue 3? Is the support for Vue 3 planned?


    I had a look at the code. I haven't actually run it, but I see 4 things that might break this component if tried with Vue 3:

    1. The component uses the createElement (aka h) function from render callback

      // Vue component options
      {
        name: 'MyComponent'
        ...
        render(h) {
          ...
          return h(...)
        }
      }
      

      whereas Vue 3 compatible way is to import it from vue (see docs)

      import { h } from 'vue';
      
      // Vue component options
      {
        name: 'MyComponent'
        ...
        render() {
          ...
          return h(...)
        }
      }
      
    2. The component uses $scopedSlots, which are merged to slots in Vue 3 (see docs).

    3. Custom events emitted. To make it in line with Vue 3, the custom event errorCaptured should be documented in emits Vue component option (see docs).

    4. VNode interaction. Don't know if the VNode API has changed in a way that could affect package, but it should be tested.

    opened by JuroOravec 3
  • Multiple slotted content

    Multiple slotted content

    Totally forgot I left in this.$slots.default[0]. Might want the ability to wrap multiple components at once so we'll want to render all of them. May need to delegate this to a functional component so we can return multiple root elements.

    enhancement good first issue 
    opened by dillonchanis 1
  • Not working: Cannot read properties of null (reading 'setupContext')

    Not working: Cannot read properties of null (reading 'setupContext')

    when im trying to use it I get "Cannot read properties of null (reading 'setupContext')"

    <vue-error-boundary :fall-back="null"></vue-error-boundary>

    import VueErrorBoundary from 'vue-error-boundary';

    opened by rendomnet 1
  • TypeScript compatibility via index.d.ts file

    TypeScript compatibility via index.d.ts file

    This package is not available to those using strict compilation settings or linting standards. It's not due to a bug in the package itself, but the lack of a definitions file.

    opened by Fermain 1
  • Composition UI support

    Composition UI support

    Hey there.

    I had need of an ErrorBoundary on my project, but am trying to stay inside TypeScript. With the release of the Composition UI, it's a little more possible. I had a go at creating a version of what you've done using it. Thought you might care to use it as a starting point if you begin supporting it or TS:

    https://gist.github.com/lancegliser/9a4d22dbab2113a45d5ddb04f5825071

    The relevant bit is:

    import {
      createComponent,
      createElement,
      onErrorCaptured,
      reactive,
      SetupContext
    } from "@vue/composition-api";
    import DefaultFallbackUI from "./ErrorBoundaryFallbackUI.vue";
    import { IErrorBoundaryState } from "@/components/errorBoundary/IErrorBoundary";
    import { Vue as VueType } from "vue/types/vue";
    import { VNode } from "vue";
    
    const isObjectEmpty = (obj: Object) =>
      Object.entries(obj).length === 0 && obj.constructor === Object;
    // https://github.com/posva/vue-promised/blob/master/src/index.js
    const convertVNodeArray = (h: Function, wrapperTag: string, nodes: VNode[]) => {
      // for arrays and single text nodes
      if (nodes.length > 1 || !nodes[0].tag) return h(wrapperTag, {}, nodes);
      return nodes[0];
    };
    
    interface IProps {
      stopPropagation: boolean;
      fallBack: Object;
      onError: Function;
      tag: string;
    }
    
    const defaultOnErrorFallback = () => {};
    const ErrorBoundary = createComponent<IProps>({
      name: "ErrorBoundary",
      props: {
        stopPropagation: {
          type: Boolean,
          default: false
        },
        fallBack: {
          type: Object,
          default: () => DefaultFallbackUI
        },
        onError: {
          type: Function,
          default: defaultOnErrorFallback
        },
        tag: {
          type: String,
          default: "div"
        }
      },
      setup(props: IProps, context: SetupContext): () => VNode | null {
        const { state } = useState(props);
        return (): VNode | null => {
          const fallback = createElement(props.fallBack, {
            props: { state }
          });
          if (state.error) {
            return Array.isArray(fallback)
              ? convertVNodeArray(createElement, props.tag, fallback)
              : fallback;
          }
          if (isObjectEmpty(context.slots)) {
            console.warn("ErrorBoundary component must have child components.");
            return null;
          }
          const contents = context.slots.default();
          return Array.isArray(contents)
            ? convertVNodeArray(createElement, props.tag, contents)
            : contents;
        };
      }
    });
    export default ErrorBoundary;
    function useState(props: IProps) {
      const state = reactive({
        error: undefined
      } as IErrorBoundaryState);
      onErrorCaptured((error: Error, vm: VueType, info: string = "") => {
        state.error = error;
        props.onError(error, vm, info);
        if (props.stopPropagation) {
          return false;
        }
      });
      return { state };
    }
    
    opened by lancegliser 2
  • Use a slot for fallback?

    Use a slot for fallback?

    This is a really nice component, thanks! It would be nice not to have to create a whole component just for a bit of fallback text/html. Is it possible to just have a slot for the fallback?

    opened by garyo 6
Owner
Dillon Chanis
Software Developer
Dillon Chanis
Reusable component to add spaced-repetition based flashcard to any webpage. No servers required because user's progress remains in localStorage.

flashcard VueJS components to add spaced-repetition based flashcard to any webpage. Less than 5KB gzipped, and 15KB unzipped. Demo: https://nilesh.tri

null 28 Jul 31, 2022
A reusable skeleton card component written in Vuejs

skeleton-card-vuejs A reusable skeleton card component written in Vuejs Motivation Loader spinner are boring. A skeleton card gives to the user a clue

Francesco Saverio Zuppichini 142 Nov 10, 2022
A reusable NFT Preview Card Built With Vue.js

Frontend Mentor - NFT preview card component solution This is a solution to the

Rodrigo Vergara 4 Dec 4, 2022
🌟 DataFormsJS 🌟 A minimal JavaScript Framework and standalone React and Web Components for rapid development of high quality websites and single page applications.

?? Welcome to DataFormsJS! Thanks for visiting! ?? ?? ?? ?? ?? ?? 中文 (简体) 欢迎来到 DataFormsJS Español Bienvenido a DataFormsJS Português (do Brasil) Bem

DataFormsJS 156 Dec 8, 2022
Applications for any device with HTML, CSS and JavaScript - free and open source!

App Framework App Framework development has ended. I recommend using the Framework7 CLI instead. iOS and Android Apps with HTML & JavaScript - App Fra

null 646 Dec 28, 2022
Simple diceware password generator built using Vue and plain JavaScript

Vue Diceware This is simple diceware password generator built using Vue and plain JavaScript. It generates passwords consisting 4 up to 10 words using

Maciek Talaśka 0 Feb 3, 2021
A bundler for javascript and friends. Packs many modules into a few bundled assets

A bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through

webpack 62.3k Jan 9, 2023
Learning Resources App is a simple web application built using Vue js, HTML, CSS, and JavaScript

Learning Resources App is a simple web application built using Vue js, HTML, CSS, and JavaScript

norhan reda 4 Sep 4, 2022
A small game written in Javascript

Vue 3 + Vite This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 <script setup> SFCs, check out the scrip

Yosef Yudha Wijaya 2 Dec 4, 2022
Singlepage.js is a pure Javascript portal platform for building modular Web applications

Singlepage.js is a pure Javascript portal platform for building modular Web applications.

Padmanabh Dabke 0 Jan 22, 2021
GSAP is a robust JavaScript toolset that turns developers into animation superheroes

GSAP is a robust JavaScript toolset that turns developers into animation superheroes. Build high-performance animations that work in every major browser. Animate CSS, SVG, canvas, React, Vue, WebGL, colors, strings, motion paths, generic objects...anything JavaScript can touch! GSAP's ScrollTrigger plugin lets you create jaw-dropping scroll-based animations with minimal code.

GreenSock 15.4k Jan 5, 2023
Veo JavaScript linting rules

@veobot/eslint-config Veo Robotics ESLint rules for all JavaScript / TypeScript projects Installation Install the package and all of its peer dependen

Veo Robotics 1 Dec 11, 2021
A little retry tool for javascript/typescript

ts-retry A little retry tool to execute a function until the function is successful. Can also bind a timeout to a function. This lib is usable in type

Franck Ledoux 22 Dec 28, 2022
Type definitions for JavaScript APIs of AMap in TypeScript

amap-js-api-typings Type definitions for JavaScript APIs of AMap in TypeScript English | 简体中文 Installation npm install amap-js-api-typings Usage Add t

Qingrong Ke 7 Dec 30, 2021
Vue component for drag-and-drop to design and build mobile website.

vue-page-designer Live Demo A drag-and-drop mobile website builder base on Vue. Install yarn add vue-page-designer You can start it quickly, in main.j

Yuan Zhu 833 Jan 3, 2023
A simple and beautiful Vue chat component backend agnostic, fully customisable and extendable.

vue-beautiful-chat vue-beautiful-chat provides an intercom-like chat window that can be included easily in any project for free. It provides no messag

Matteo Merola 1.2k Jan 7, 2023
A Vue.js component for creating polls, voting and showing results. It’s easy to implement and easy to customize.

vue-easy-polls A Vue.js component for creating polls, voting and showing results. It’s easy to implement and easy to customize. Demo See live demo her

UPDIVISION 13 Nov 24, 2022
Vue component provides textarea with automatically adjustable height and without any wrappers and dependencies

vue-textarea-autosize The plugin for Vue.js provides the Vue component implements textarea with automatically adjustable height and without any wrappe

Devstark 126 Dec 9, 2022
Vue Cookies Consent - Nice and clean component to display message about cookies in Vue and Nuxt.js

Vue Cookies Consent Nice and clean component to display message about cookies in Vue and Nuxt.js ?? Demo ?? Installation NPM npm install --save @norvi

Norvik IT 8 Sep 26, 2022