рдЖрдЬ рдореИрдВ рдЖрдкрдХреЛ рд░рд┐рдПрдХреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рд░реАрдпрд▓-рдЯрд╛рдЗрдо рддреНрд░реБрдЯрд┐ рдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдКрдВрдЧрд╛ред рдлреНрд░рдВрдЯ-рдПрдВрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрдорддреМрд░ рдкрд░ рддреНрд░реБрдЯрд┐ рдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреБрдЫ рдХрдВрдкрдирд┐рдпрд╛рдБ рдЕрдХреНрд╕рд░ рдмрдЧ рдЯреНрд░реИрдХрд┐рдВрдЧ, рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг, рдкрд░реАрдХреНрд╖рдг рдЖрджрд┐ рдХреЗ рдмрд╛рдж рдЙрд╕ рдкрд░ рд╡рд╛рдкрд╕ рд▓реМрдЯрдирд╛ рдмрдВрдж рдХрд░ рджреЗрддреА рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдЙрддреНрдкрд╛рдж рдХреЛ рдмреЗрд╣рддрд░реА рдХреЗ рд▓рд┐рдП рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдмрд╕ рдРрд╕рд╛ рдХрд░реЗрдВ!
1. рдЖрдкрдХреЛ рд╕рдВрддрд░реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ?
рдореИрдВ рдорд╛рдирддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рдЙрддреНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рдмрдЧреНрд╕ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ
рдХреНрдпрд╛ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ?
рдареАрдХ рд╣реИ, рдЖрдЗрдП рд╡рд┐рд╡рд░рдг рджреЗрдЦреЗрдВред
рдбреЗрд╡рд▓рдкрд░реНрд╕ рджреНрд╡рд╛рд░рд╛ рд╕реЗрдВрдЯреНрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдкреНрд░рдореБрдЦ рдХрд╛рд░рдг:
- рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХреЛрдб рддреИрдирд╛рдд рдХрд░рддреЗ рд╕рдордп рдЖрдкрдХреЛ рдЬреЛрдЦрд┐рдореЛрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓рддреА рд╣реИ
- рдХреЛрдб рдкрд░реАрдХреНрд╖рдг рдореЗрдВ QA рдХреА рд╕рд╣рд╛рдпрддрд╛ рдХрд░реЗрдВ
- рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рддреНрд╡рд░рд┐рдд рд╕реВрдЪрдирд╛рдПрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
- рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╢реАрдШреНрд░рддрд╛ рд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛
- рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдХ рдкреИрдирд▓ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдкреНрд░рджрд░реНрд╢рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
- рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛/рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЦрдВрдб рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХреНрд░рдорд┐рдд рдХрд░реЗрдВ
рд╕реАрдИрдУ/рд▓реАрдб рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рдореБрдЦреНрдп рдХрд╛рд░рдг
- рдкреИрд╕реЗ рдмрдЪрд╛рдПрдВ (рд╕рдВрддрд░реА рдЖрдкрдХреЗ рд╕рд░реНрд╡рд░ рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ)
- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
- рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рдпрд╣ рд╕рдордЭрдирд╛ рдХрд┐ рдЖрдкрдХреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХреНрдпрд╛ рдЧрдбрд╝рдмрдбрд╝ рд╣реИ
- рдЖрдкрдХреЗ рдРрдк рд╕реЗ рд▓реЛрдЧреЛрдВ рдХреЛ рд╣реЛрдиреЗ рд╡рд╛рд▓реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рдордЭрдирд╛
- рдЙрди рд╕реНрдерд╛рдиреЛрдВ рдХреЛ рдвреВрдВрдврдиреЗ рдореЗрдВ рдЖрдкрдХреА рд╕рд╣рд╛рдпрддрд╛ рдХрд░реЗрдВ рдЬрд╣рд╛рдВ рдЖрдкрдХреЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ рдЧрд▓рддрд┐рдпрд╛рдВ рдХреА рд╣реИрдВ
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реЛрдЧреАред рдЖрдк рдЕрдкрдиреЗ рдмреЙрд╕ рдХреЛ рд╕реЗрдВрдЯреНрд░реА рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░рдгреЛрдВ рдХреА рдЗрд╕ рд╕реВрдЪреА рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╡реНрдпрд╡рд╕рд╛рдп рд╕реВрдЪреА рдХреЗ рдЕрдВрддрд┐рдо рдЖрдЗрдЯрдо рд╕реЗ рд╕рд╛рд╡рдзрд╛рди рд░рд╣реЗрдВред
рдХреНрдпрд╛ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ?
рд╕рдВрддрд░реА рдХреНрдпрд╛ рд╣реИ?
рд╕реЗрдВрдЯреНрд░реА рдПрдХ рдУрдкрди рд╕реЛрд░реНрд╕ рдмрдЧ рдЯреНрд░реИрдХрд┐рдВрдЧ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ рдЬреЛ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рдХреНрд░реИрд╢ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдФрд░ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рдпрд╣ рди рднреВрд▓реЗрдВ рдХрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЖрдкрдХреЛ рджрдХреНрд╖рддрд╛ рдмрдврд╝рд╛рдиреЗ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдиреБрднрд╡ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╕реЗрдВрдЯреНрд░реА рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ, рдиреЛрдб, рдкрд╛рдпрдерди, рдкреАрдПрдЪрдкреА, рд░реВрдмреА, рдЬрд╛рд╡рд╛ рдФрд░ рдЕрдиреНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред
2. рд▓реЙрдЧрд┐рди рдХрд░реЗрдВ рдФрд░ рдПрдХ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ
- рдЕрдкрдирд╛ рд╕рдВрддрд░реА рдЦрд╛рддрд╛ рдЦреЛрд▓реЗрдВ. рдЖрдкрдХреЛ рд▓реЙрдЧ рдЗрди рдХрд░рдирд╛ рдкрдбрд╝ рд╕рдХрддрд╛ рд╣реИ. (рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕реЗрдВрдЯреНрд░реА рдЖрдкрдХреЗ рд╕рд░реНрд╡рд░ рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ)
- рдЕрдЧрд▓рд╛ рдХрджрдо рдПрдХ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдирд╛ рд╣реИ
- рд╕реВрдЪреА рд╕реЗ рдЕрдкрдиреА рднрд╛рд╖рд╛ рдЪреБрдиреЗрдВ. (рд╣рдо рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред "рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдВ" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ)
рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░реЗрдВ. рд╕реЗрдВрдЯреНрд░реА рдХреЛ рдПрдХ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рдХреИрд╕реЗ рдПрдХреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рдП рдЗрд╕рдХрд╛ рдПрдХ рдореВрд▓ рдЙрджрд╛рд╣рд░рдг рдиреАрдЪреЗ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
import * as Sentry from '@sentry/browser';
// Sentry.init({
// dsn: "<https://[email protected]/1432138>"
// });
// should have been called before using it here
// ideally before even rendering your react app
class ExampleBoundary extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
componentDidCatch(error, errorInfo) {
this.setState({ error });
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
render() {
if (this.state.error) {
//render fallback UI
return (
<a onClick={() => Sentry.showReportDialog()}>Report feedback</a>
);
} else {
//when there's not an error, render children untouched
return this.props.children;
}
}
}
рд╕реЗрдВрдЯреНрд░реА рдХреЗ рдкрд╛рд╕ рдПрдХ рд╕рд╣рд╛рдпрдХ рд╡рд┐рдЬрд╝рд╛рд░реНрдб рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдЖрдЧреЗ рдХреНрдпрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдк рдЗрди рдЪрд░рдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ. рдореИрдВ рдЖрдкрдХреЛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЕрдкрдирд╛ рдкрд╣рд▓рд╛ рдПрд░рд░ рд╣реИрдВрдбрд▓рд░ рдХреИрд╕реЗ рдмрдирд╛рдПрдВред рдмрдврд╝рд┐рдпрд╛, рд╣рдордиреЗ рдПрдХ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рд╣реИ! рдЪрд▓рд┐рдП рдЕрдЧрд▓реЗ рдЪрд░рдг рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВ
3. рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдФрд░ рд╕рдВрддрд░реА рдПрдХреАрдХрд░рдг
рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ npm рдкреИрдХреЗрдЬ рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
npm i @sentry/browser
рдЕрдкрдиреЗ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд╕реЗрдВрдЯреНрд░реА рдкреНрд░рд╛рд░рдВрдн рдХрд░реЗрдВ:
Sentry.init({
// dsn: #dsnUrl,
});
DSN рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ -> рд╕реЗрдЯрд┐рдВрдЧреНрд╕ -> рдХреНрд▓рд╛рдЗрдВрдЯ рдХреБрдВрдЬреА рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИред рдЖрдк рдЦреЛрдЬ рдмрд╛рд░ рдореЗрдВ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреБрдВрдЬрд┐рдпрд╛рдБ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред
componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
4. рдкрд╣рд▓реА рддреНрд░реБрдЯрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдирд╛
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдбреАрдЬрд╝рд░ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рдВрдЧреАрдд рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдЖрдк рдЗрд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ
рд╣рдореЗрдВ рдПрдХ рдмрдЯрди рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ рдХреЙрд▓ рдХрд░реЗ рджрд┐рд▓рд╛рд╕рд╛ рджреЗрдирд╛ ╤Б рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛.рдИрдореЗрд▓. рдЗрд╕ рдХреНрд░рд┐рдпрд╛ рдХреЗ рдмрд╛рдж рд╣рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП: рдзреНрдпрд╛рди рдореЗрдВ рди рдЖрдпрд╛ рд▓реЗрдЦрди рддреНрд░реБрдЯрд┐ (рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╕реЗ рд╕рдВрдкрддреНрддрд┐ рдирд╣реАрдВ рдкрдврд╝ рд╕рдХрддрд╛ email
) рдЙрдкрдпреЛрдХреНрддрд╛ рд╡рд╕реНрддреБ рдЧреБрдо рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдгред рдЖрдк рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЕрдкрд╡рд╛рдж.
<button type="button" onClick={() => console.log(user.email)}>
Test Error button
</button>
рдкреВрд░рд╛ рдХрдВрдЯреЗрдирд░ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
import React, { Component } from "react";
import { connect } from "react-redux";
import { Input, List, Skeleton, Avatar } from "antd";
import * as Sentry from "@sentry/browser";
import getList from "../store/actions/getList";
const Search = Input.Search;
const mapState = state => ({
list: state.root.list,
loading: state.root.loading
});
const mapDispatch = {
getList
};
class Container extends Component {
constructor(props) {
super(props);
Sentry.init({
dsn: "https://[email protected]/1417586",
});
}
componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
render() {
const { list, loading, getList } = this.props;
const user = undefined;
return (
<div className="App">
<button
type="button"
onClick={() => console.log(user.email)}
>
test error1
</button>
<div onClick={() => Sentry.showReportDialog()}>Report feedback1</div>
<h1>Music Finder</h1>
<br />
<Search onSearch={value => getList(value)} enterButton />
{loading && <Skeleton avatar title={false} loading={true} active />}
{!loading && (
<List
itemLayout="horizontal"
dataSource={list}
locale={{ emptyText: <div /> }}
renderItem={item => (
<List.Item>
<List.Item.Meta
avatar={<Avatar src={item.artist.picture} />}
title={item.title}
description={item.artist.name}
/>
</List.Item>
)}
/>
)}
</div>
);
}
}
export default connect(
mapState,
mapDispatch
)(Container);
рдЗрд╕ рдмрдЯрди рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╣рдорд╛рд░реА рдкрд╣рд▓реА рдЧрд▓рддреА рд╣реИ
рд╣реВ-рд╣реВ!
рдпрджрд┐ рдЖрдк рд╣реЗрдбрд░ рддреНрд░реБрдЯрд┐ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдПрдХ рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред
рд╕рдВрджреЗрд╢ рдЦрд╝рд░рд╛рдм рджрд┐рдЦрддреЗ рд╣реИрдВ. рдирд┐рдГрд╕рдВрджреЗрд╣ рд╣рдордиреЗ рдпрд╣ рд╕рдордЭреЗ рдмрд┐рдирд╛ рдХрд┐ рдХреЛрдб рдХрд╣рд╛рдБ рд╣реИ, рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рджреЗрдЦреЗ рд╣реИрдВред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╣рдо ReactJS рдореЗрдВ рд╕реНрд░реЛрдд рдорд╛рдирдЪрд┐рддреНрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдирд╣реАрдВ рд╣реИрдВред
рдореИрдВ рд╕реНрд░реЛрдд рдорд╛рдирдЪрд┐рддреНрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ рднреА рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдЗрд╕рд╕реЗ рдпрд╣ рд▓реЗрдЦ рдореЗрд░реА рдЕрдкреЗрдХреНрд╖рд╛ рд╕реЗ рдЕрдзрд┐рдХ рд▓рдВрдмрд╛ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
рдЖрдк рдЗрд╕ рд╡рд┐рд╖рдп рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
5. рдЙрдкрдпреЛрдЧ рдкрд╣рд░реЗрджрд╛рд░ рдЕрдВрдд рдмрд┐рдВрджреБ рдХреЗ рд╕рд╛рде API
рдареАрдХ рд╣реИред рд╣рдордиреЗ рдкрд┐рдЫрд▓реЗ рдкреИрд░рд╛рдЧреНрд░рд╛рдл рдореЗрдВ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЕрдкрд╡рд╛рдж рдХреЛ рдХрд╡рд░ рдХрд┐рдпрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдо XHR рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рдХрд░реЗрдВрдЧреЗ?
рд╕реЗрдВрдЯреНрд░реА рдореЗрдВ рдХрд╕реНрдЯрдо рдПрд░рд░ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рднреА рд╣реИред рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдкреАрдЖрдИ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ред
Sentry.captureException(err)
рдЖрдк рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди, рдИрдореЗрд▓ рдЖрджрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддреНрд░реБрдЯрд┐ рдирд╛рдо, рд╕реНрддрд░, рдбреЗрдЯрд╛ рдЬреЛрдбрд╝реЗрдВ, рдЕрджреНрд╡рд┐рддреАрдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
superagent
.get(`https://deezerdevs-deezer.p.rapidapi.com/search?q=${query}`)
.set("X-RapidAPI-Key", #id_key)
.end((err, response) => {
if (err) {
Sentry.configureScope(
scope => scope
.setUser({"email": "[email protected]"})
.setLevel("Error")
);
return Sentry.captureException(err);
}
if (response) {
return dispatch(setList(response.body.data));
}
});
рдореИрдВ рдХреИрдЪ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред
import * as Sentry from "@sentry/browser";
export const apiCatch = (error, getState) => {
const store = getState();
const storeStringify = JSON.stringify(store);
const { root: { user: { email } } } = store;
Sentry.configureScope(
scope => scope
.setLevel("Error")
.setUser({ email })
.setExtra("store", storeStringify)
);
// Sentry.showReportDialog(); - If you want get users feedback on error
return Sentry.captureException(error);
};
рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рдХреЙрд▓ рдореЗрдВ рдЖрдпрд╛рдд рдХрд░реЗрдВред
export default query => (dispatch, getState) => {
superagent
.get(`https://deezerdevs-deezer.p.rapidapi.com/search?q=${query}`)
.set("X-RapidAPI-Key", #id_key)
.end((error, response) => {
if (error) {
return apiCatch(error, getState)
}
if (response) {
return dispatch(setList(response.body.data));
}
});
};
рдЖрдЗрдП рддрд░реАрдХреЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ:
- рд╕реЗрдЯрд▓реЗрд╡рд▓ рдЖрдкрдХреЛ рд╕рдВрддрд░реА рдбреИрд╢рдмреЛрд░реНрдб рдореЗрдВ рдПрдХ рд▓реЗрд╡рд▓ рддреНрд░реБрдЯрд┐ рдбрд╛рд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЧреБрдг рд╣реИрдВ - 'рдШрд╛рддрдХ', 'рддреНрд░реБрдЯрд┐', 'рдЪреЗрддрд╛рд╡рдиреА', 'рд▓реЙрдЧ', 'рдЬрд╛рдирдХрд╛рд░реА, 'рдбреАрдмрдЧ', 'рдорд╣рддреНрд╡рдкреВрд░реНрдг')ред
- рд╕реЗрдЯ рдпреВрдЬрд╝рд░ рдХрд┐рд╕реА рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ (рдЖрдИрдбреА, рдИрдореЗрд▓ рдкрддрд╛, рднреБрдЧрддрд╛рди рдпреЛрдЬрдирд╛, рдЖрджрд┐) рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред
- рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реЗрдЯ рдХрд░реЗрдВ рдЖрдкрдХреЛ рдХрд┐рд╕реА рднреА рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реНрдЯреЛрд░ред
рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рдмрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ showReportDialog рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
Sentry.showReportDialog();
рдирд┐рд╖реНрдХрд░реНрд╖:
рдЖрдЬ рд╣рдордиреЗ рд╕реЗрдВрдЯреНрд░реА рдХреЛ рд░рд┐рдПрдХреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдмрддрд╛рдпрд╛ред
тЖТ рдЯреЗрд▓реАрдЧреНрд░рд╛рдо рдЪреИрдЯ рджреНрд╡рд╛рд░рд╛
рд╕реНрд░реЛрдд: www.habr.com