dillonchanis / vue-error-boundary

A reusable error boundary component for catching JavaScript errors and displaying fallback UIs.
MIT License
91 stars 9 forks source link

Use a slot for fallback? #3

Open garyo opened 5 years ago

garyo commented 5 years ago

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?

dillonchanis commented 5 years ago

Hey @garyo sorry for the late response, I've been swamped lately. I think this is a great idea. I might be able to tackle this in a bit unless you want to shoot a PR over?

garyo commented 5 years ago

I'm not enough of a Vue expert yet to try that :-)

dillonchanis commented 5 years ago

I've been working on this this morning. Figured I'd share the proposed API. We'll expose a boundary slot scope. On that slot scope there will be three properties:

Example usage:

<error-boundary #boundary="{ hasError }">
  <div v-if="!hasError">No error occurred.</div>
  <div v-else>Message to appear if error occurred.</div>
</error-boundary>
garyo commented 5 years ago

That looks OK to me. Alternatively (or also?) you could have a named "error" slot as well as the default slot for the content to wrap:

<error-boundary #boundary="{ hasError, errmsg}">
  <ImUnstable/>
  <MoreContent/>
  <div slot="error" class="error">An error occurred: {{ errmsg }}</div>
</error-boundary>

That way users don't have to fiddle with v-if/v-else.

dillonchanis commented 5 years ago

I think the above might not compile.

<div v-slot:error> wouldn't work because slots only work on <template> or components. Furthermore, using the slot-scope on the parent <error-boundary> would throw the error:

To avoid scope ambiguity, the default slot should also use <template> syntax when there are other named slots.

Which, if I'm not mistaken, you'd have to end up doing something like:

<error-boundary>
  <template #boundary="{ hasError, ... }">
     Has access to hasError/err/info.
  </template>
  <template v-slot:error>
    Default fallback content. Has no access to error boundary state.
  </template>
</error-boundary>

I could be wrong since I haven't kept up with Vue these past few months 😅

I'll probably go ahead and push the above live while I look into just the slot option.

garyo commented 5 years ago

You're right -- you have to use a <template> for the error message unless it's already a component. And I see your point about where to put the slot props -- I'm still learning all this stuff! Clearly the default slot doesn't normally need any access to the error slot props.

So perhaps the "normal" use would be something like this:

<error-boundary>
  <ImUnstable/>
  <MoreContent/>
  <template v-slot:boundary="{errmsg}">
    <div class="error">An error occurred: {{ errmsg }}</div>
  </template>
</error-boundary>

Is that sort of like what you meant? That looks nice and usable to me. Though maybe it's better to name the scope "error", like v-slot:error="{errmsg"} ?