# 7.2 Obsługa błędów w kontekście komponentów.
Podczas pracy z API oraz Vue SRR możemy spotkać się z niefajną obsługa błędów na poziomie server-side.

Prosty przykład:
<TextWithImage :image="image.rows[1].columns[1]" .../>
Jest to potencjalny przypadek aby serwer aplikacji frontendowej wyrzucił nam stronę typu server side error, ponieważ odnosimy się tutaj do wybranych elementów tablicy, nie sprawdzając wcześniej czy obiekt image zawiera pole rows oraz czy wartość pola rows jest tablicą/czy ma jakieś dzieci oraz czy pierwsze dziecko pola rows zawiera pole columns itd.
Na frontendzie powinniśmy te wsyzstkie pola sprawdzić, tak aby nie dopuścić do sytuacji w której pobieramy wartości z jakiegoś obiektu, które potencjalnie mogą nie istnieć. Można to rozwiązać na kilka sposób takich jak v-if w templatce, wartość computed lub optional chaining.
Po stronie serwerowej warto się zabezpieczyć przed wyświetleniem error page, pozwalając na wyrenderowanie strony z pominięciem wadliwego komponentu.
Aby to zrobić należy użyć hooka errorCaptured (opens new window).
Najprostszy sposób to zwrócenie false wewnątrz hooka errorCaptured, natomiast w ten sposób pozbędziemy się błędów tak, że nie będziemy o nich wiedzieć.
<script>
export default {
name: 'ErrorBoundary',
errorCaptured(err, vm, info) {
return false
}
}
</script>
2
3
4
5
6
7
8
WARNING
Nadpisując hook errorCaptured poprzez zwrócenie false automatycznie zatrzymujemy propagacje eventu informującego o błędzie do globalnej metody config.errorHandler, przez co inne metody, które używały tego hooka mogą przestać działać. Musimy pamiętać o tym w kontekście zbierania błędów - np. wtyczka Sentry jest oparta o ten hook. Zatrzymując propagację eventu na poziomie komponentów jesteśmy odpowiedzialni za poinformowanie o evencie błędu ręcznie.
# Komponent ErrorBoundary
Nasz komponent powinien spełniać kilka założeń:
- Ominięcie strony błędu w przypadku trybu produkcyjnego oraz wyświetlenie strony błędu w trybie deweloperskim (lub użycie property
stopPropagationz wartością true) - W przypadku trybu produkcyjnego oraz SSR powinniśmy logować wszystkie błędy.
- Event błędu powinien być możliwy do obsłużenia z zewnątrz, dlatego komponent będzie gotowy do przyjęcia property o nazwie
onErrororaz wartości typufunction, dodatkowo będziemy emitować event. - Komponent powinien zbierać wszystkie błędy, które wystąpiły na danej stronie, dlatego będziemy zbierać je w tablicy
errors
Stwórzmy więc komponent o nazwie ErrorBoundary, który będzie "wychwytywaczem" błędów z komponentów dzieci.
components/utilities/ErrorBoundary.vue:
<script>
export default {
name: 'ErrorBoundary',
props: {
stopPropagation: {
type: Boolean,
default: null,
},
onError: {
type: Function,
default: null,
},
},
data() {
return {
errors: [],
}
},
errorCaptured(err, vm, info) {
this.errors.push({
err,
vm,
info,
})
this.$emit('errorCaptured', { err, vm, info })
if (this.onError) this.onError(err, vm, info)
if (!this.$nuxt.context.isDev && this.$isServer) {
console.error(`Error in ${vm.type} `, err)
}
return this.stopPropagation !== null
? !this.stopPropagation
: this.$nuxt.context.isDev
},
render(h) {
const content = this.$slots.default
return Array.isArray(content) && (content.length > 1 || !content[0].tag)
? h('div', {}, content)
: content
},
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# Przykład użycia
Komponentu możemy użyć np. na poziomie strony wtedy będziemy wychtywać błędy z wszystkich dynamicznych komponentów serwowanych przez API.
pages/_.vue:
<template>
<error-boundary :on-error="handleError">
<be-dynamic
:page="page.page"
:content="page.content"
:type="backendLayout"
/>
</error-boundary>
</template>
<script>
import defaultPage from '~typo3/mixins/page/default'
import ErrorBoundary from '../components/utilities/ErrorBoundary'
export default {
components: {
ErrorBoundary
},
mixins: [defaultPage],
methods: {
handleError(err) {
if (this.$sentry) {
this.$sentry.captureException(err)
}
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
TIP
Jeżeli zbieramy błędy przez serwisy takie jak Sentry powinniśmy odpalić metodę informującą Sentry o napotkanym błędzie lub ewentualnym console.log(). Dlatego użyliśmy onError property do przekazania funkcji jaka ma się odpalić przy napotkanym błędzie.