Изследваме използването на Sentry с React.

Тази статия е част от серия, която започва с отчета за грешки Sentry на примера: .
Имплементация на React
Първо трябва да добавим нов проект Sentry за това приложение; от сайта на Sentry. В този случай избираме React.
Отново имплементираме нашите два бутона, Hello и Error, приложението с React. Започваме с създаването на нашето стартерно приложение:
npx create-react-app react-appСлед това импортираме пакета Sentry:
yarn add @sentry/browserи го инициализираме:
react-app / src / index.js
...
import * as Sentry from '@sentry/browser';
const RELEASE = '0.1.0';
if (process.env.NODE_ENV === 'production') {
Sentry.init({
dsn: 'https://303c04eac89844b5bfc908ceffc6757c@sentry.io/1289887',
release: RELEASE,
});
}
...Наблюдения:
- По време на разработката имаме други механизми за наблюдение на проблеми, например консолата, затова включваме Sentry само за производствени сборки.
След това имплементираме нашите бутони Hello и Error и ги добавяме в приложението:
react-app / src / Hello.js
import React, { Component } from 'react';
import * as Sentry from '@sentry/browser';
export default class Hello extends Component {
state = {
text: '',
};
render() {
const { text } = this.state;
return (
<div>
<button
onclick="{this.handleClick}"
>
Hello
</button>
<div>{text}</div>
</div>
)
}
handleClick = () => {
this.setState({
text: 'Здравей свят',
});
try {
throw new Error('Хванато');
} catch (err) {
if (process.env.NODE_ENV !== 'production') {
return;
}
Sentry.captureException(err);
}
}
}react-app / src / MyError.js
import React, { Component } from 'react';
export default class MyError extends Component {
render() {
return (
<div>
<button
onclick="{this.handleClick}"
>
Грешка
</button>
</div>
)
}
handleClick = () => {
throw new Error('Uncaught');
}
}react-app / src / App.js
...
import Hello from './Hello';
import MyError from './MyError';
class App extends Component {
render() {
return (
<div classname="App">
...
<hello />
<myerror />
</div>
);
}
}
export default App;Проблема (Изходни карти)
Можем да тестваме Sentry с производствена сборка, като въведем:
yarn buildи от папката build напишете:
npx http-server -c-1Проблемът, с който ще се сблъскаме веднага, е, че записите за грешки Sentry сочат към номера на редовете в намален пакет; не много полезно.

Услугата Sentry обяснява това, като извлича изходни карти за намаления пакет след получаване на грешката. В този случай работим от localhost (недостъпен за услугата Sentry).
Решения (Изходни карти)
Решението на този проблем е да стартираме приложението от публичен уеб сървър. Един прост отговор на това е да се използва услугата GitHub Pages (безплатно). Стъпките за използване обикновено са следните:
Копирайте съдържанието на папката build в папка docs в коренната директория на хранилището.
Активирайте GitHub Pages в хранилището (от GitHub), за да използвате папката docs в master клон
Нанесете промените в GitHub
Забележка: след като разбрах, че трябва да използвам create-create-app функцията homepage, за да стартирам приложението. Става въпрос за добавяне на следното в package.json:
"homepage": "https://larkintuckerllc.github.io/hello-sentry/"Окончателната версия на стартираното приложение е достъпна на следния адрес:
Илюстрация на хванати грешки
Нека преминем през натискането на бутона Hello.

С грешката, която се появява по следния начин:

Наблюдения:
- Този отчет за грешка не може да бъде по-ясен. БРАВО.
Илюстрация на необработени грешки
По подобен начин, нека преминем през натискането на бутона Грешка.

С грешката, която се появява по следния начин:

Най-добра обработка на неизчислени грешки (рендериране)
Въведение в границите на грешките
Грешка в JavaScript в частта на потребителския интерфейс не трябва да нарушава работата на цялото приложение. За да се реши този проблем за потребителите на React, React 16 въвежда нова концепция "граници на грешките".
Границите на грешките са компоненти на React, които улавят JavaScript грешки на всяко място в своето дъщерно дърво от компоненти, регистрират тези грешки и показват резервен потребителски интерфейс вместо дървото от компоненти, което се е сринало. Границите на грешките улавят грешки по време на рендериране, в методи на жизнения цикъл и в конструктори на цялото дърво под тях.
…
Ново поведение за неоткритите грешки
Тази промяна е от съществено значение. Започвайки от React 16, грешки, които не са хванати от някоя граница на грешките, ще доведат до демонтиране на цялото дърво от компоненти на React.
— Дан Абрамов —
Важно уточнение, което ми отне известно време, за да разбера, е, че посоченото по-горе поведение работи само с грешки, генерирани в метода на рендериране (или, което е по-вероятно, в който и да е от методите на жизнения цикъл). Например, използването на граници на грешките няма да донесе никаква полза с нашия бутон Грешка; тази грешка е била в обработчика на кликвания.
Нека създадем пример за грешка при визуализация, а след това да използваме граници на грешките за по-елегантна обработка на грешката.
react-app / src / MyRenderError
import React, { Component } от 'react';
export default class MyRenderError extends Component {
state = {
flag: false,
};
render() {
const { flag } = this.state;
return (
<div>
<button
onclick="{this.handleClick}"
>
Грешка при извеждане
</button>
{ flag && <div>{flag.busted.bogus}</div> }
</div>
)
}
handleClick = () => {
this.setState({
flag: true,
});
}
}Наблюдение:
При натискане на бутон, React ще се показва flag.busted.bogus, който предизвиква грешка
Без граница на грешките цялото дърво от компоненти ще бъде демонтирано.
След това пишем нашия код за граница на грешките (използва новия метод на жизнения цикъл componentDidCatch); това е по същество примерът, приведен в статията на Дан Абрамов:
react-app / src / ErrorBoundary.js
import React, { Component } from 'react';
import * as Sentry from '@sentry/browser';
export default class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(err, info) {
this.setState({ hasError: true });
Sentry.captureException(err);
}
render() {
if (this.state.hasError) {
return <h1>Нещо се обърка.</h1>;
}
return this.props.children;
}
}Накрая, използваме този компонент:
react-app / src / App.js
...
import MyRenderError from '.\/MyRenderError';
class App extends Component {
render() {
return (
<errorboundary>
<div classname="App">
...
</div>
</errorboundary>
);
}
}
...В този момент натискането на бутона Render Error показва резервен потребителски интерфейс и съобщава за грешка в Sentry.


Завършване
Надявам се, че това е било полезно за вас.
P.S.
P.S. Телеграм чат по Sentry
Източник: habr.com
