[DOC] add dedicated page on error handling

closes #632
This commit is contained in:
Géry Debongnie
2020-02-15 10:33:31 +01:00
parent 047a9c8993
commit 03585d8fea
3 changed files with 94 additions and 73 deletions
+1
View File
@@ -25,6 +25,7 @@ provided by Owl.
- [Environment](reference/environment.md) - [Environment](reference/environment.md)
- [Event Bus](reference/event_bus.md) - [Event Bus](reference/event_bus.md)
- [Event Handling](reference/event_handling.md) - [Event Handling](reference/event_handling.md)
- [Error Handling](reference/error_handling.md)
- [Hooks](reference/hooks.md) - [Hooks](reference/hooks.md)
- [Miscellaneous Components](reference/misc.md) - [Miscellaneous Components](reference/misc.md)
- [Observer](reference/observer.md) - [Observer](reference/observer.md)
+4 -65
View File
@@ -15,7 +15,6 @@
- [Form Input Bindings](#form-input-bindings) - [Form Input Bindings](#form-input-bindings)
- [References](#references) - [References](#references)
- [Dynamic sub components](#dynamic-sub-components) - [Dynamic sub components](#dynamic-sub-components)
- [Error Handling](#error-handling)
- [Functional Components](#functional-components) - [Functional Components](#functional-components)
- [SVG components](#svg-components) - [SVG components](#svg-components)
@@ -307,7 +306,7 @@ developers write components. Here is a complete description of the lifecycle of
a owl component: a owl component:
| Method | Description | | Method | Description |
| ------------------------------------------------ | ------------------------------------------------------------ | | ------------------------------------------------ | ----------------------------------------------------------- |
| **[constructor](#constructorparent-props)** | constructor | | **[constructor](#constructorparent-props)** | constructor |
| **[willStart](#willstart)** | async, before first rendering | | **[willStart](#willstart)** | async, before first rendering |
| **[mounted](#mounted)** | just after component is rendered and added to the DOM | | **[mounted](#mounted)** | just after component is rendered and added to the DOM |
@@ -315,7 +314,7 @@ a owl component:
| **[willPatch](#willpatch)** | just before the DOM is patched | | **[willPatch](#willpatch)** | just before the DOM is patched |
| **[patched](#patchedsnapshot)** | just after the DOM is patched | | **[patched](#patchedsnapshot)** | just after the DOM is patched |
| **[willUnmount](#willunmount)** | just before removing component from DOM | | **[willUnmount](#willunmount)** | just before removing component from DOM |
| **[catchError](#catcherrorerror)** | catch errors (see [error handling section](#error-handling)) | | **[catchError](#catcherrorerror)** | catch errors (see [error handling page](error_handling.md)) |
Notes: Notes:
@@ -450,8 +449,8 @@ This is the opposite method of `mounted`.
#### `catchError(error)` #### `catchError(error)`
The `catchError` method is useful when we need to intercept and properly react The `catchError` method is useful when we need to intercept and properly react
to (rendering) errors that occur in some sub components. See the section on to (rendering) errors that occur in some sub components. See the page on
[error handling](#error-handling). [error handling](error_handling.md).
### Root Component ### Root Component
@@ -744,66 +743,6 @@ component class.
Note that the `t-component` directive can only be used on `<t>` nodes. Note that the `t-component` directive can only be used on `<t>` nodes.
### Error Handling
By default, whenever an error occurs in the rendering of an Owl application, we
destroy the whole application. Otherwise, we cannot offer any guarantee on the
state of the resulting component tree. It might be hopelessly corrupted, but
without any user-visible state.
Clearly, it sometimes is a little bit extreme to destroy the application. This
is why we have a builtin mechanism to handle rendering errors (and errors coming
from lifecycle hooks): the `catchError` hook.
Whenever the `catchError` lifecycle hook is implemented, all errors coming from
sub components rendering and/or lifecycle method calls will be caught and given
to the `catchError` method. This allows us to properly handle the error, and to
not break the application.
For example, here is how we could implement an `ErrorBoundary` component:
```xml
<div t-name="ErrorBoundary">
<t t-if="state.error">
Error handled
</t>
<t t-else="">
<t t-slot="default" />
</t>
</div>
```
```js
class ErrorBoundary extends Component {
state = useState({ error: false });
catchError() {
this.state.error = true;
}
}
```
Using the `ErrorBoundary` is then extremely simple:
```xml
<ErrorBoundary><SomeOtherComponent/></ErrorBoundary>
```
Note that we need to be careful here: the fallback UI should not throw any
error, otherwise we risk going into an infinite loop (also, see the page on
[slots](slots.md) for more information on the `t-slot` directive).
Also, it may be useful to know that whenever an error is caught, it is then
broadcasted to the application by an event on the `qweb` instance. It may be
useful, for example, to log the error somewhere.
```js
env.qweb.on("error", null, function(error) {
// do something
// react to the error
});
```
### Functional Components ### Functional Components
Owl does not exactly have functional components. However, there is an extremely Owl does not exactly have functional components. However, there is an extremely
+81
View File
@@ -0,0 +1,81 @@
# 🦉 Error Handling 🦉
## Content
- [Overview](#overview)
- [Example](#example)
- [Reference](#reference)
## Overview
By default, whenever an error occurs in the rendering of an Owl application, we
destroy the whole application. Otherwise, we cannot offer any guarantee on the
state of the resulting component tree. It might be hopelessly corrupted, but
without any user-visible state.
Clearly, it sometimes is a little bit extreme to destroy the application. This
is why we have a builtin mechanism to handle rendering errors (and errors coming
from lifecycle hooks): the `catchError` hook.
## Example
For example, here is how we could implement an `ErrorBoundary` component:
```xml
<div t-name="ErrorBoundary">
<t t-if="state.error">
Error handled
</t>
<t t-else="">
<t t-slot="default" />
</t>
</div>
```
```js
class ErrorBoundary extends Component {
state = useState({ error: false });
catchError() {
this.state.error = true;
}
}
```
Using the `ErrorBoundary` is then extremely simple:
```xml
<ErrorBoundary><SomeOtherComponent/></ErrorBoundary>
```
Note that we need to be careful here: the fallback UI should not throw any
error, otherwise we risk going into an infinite loop (also, see the page on
[slots](slots.md) for more information on the `t-slot` directive).
## Reference
Whenever the `catchError` lifecycle hook is implemented, all errors coming from
sub components rendering and/or lifecycle method calls will be caught and given
to the `catchError` method. This allows us to properly handle the error, and to
not break the application.
There are important things to know:
- If an error that occured in the internal rendering cycle is not caught, then
Owl will destroy the full application. This is done on purpose, because Owl
cannot guarantee that the state is not corrupted from this point on.
- errors coming from event handlers are NOT managed by `catchError` or any other
owl mechanism. This is up to the application developer to properly recover
from an error
Also, it may be useful to know that whenever an error is caught, it is then
broadcasted to the application by an event on the `qweb` instance. It may be
useful, for example, to log the error somewhere.
```js
env.qweb.on("error", null, function(error) {
// do something
// react to the error
});
```