Õppige, kuidas rakendada robustset Reacti veakäsitlusstrateegiat, kasutades veapiiride puid sujuvaks talitluse halvenemiseks ja paremaks kasutajakogemuseks.
Reacti veapiiride puu: hierarhiline veakäsitlus robustsete rakenduste jaoks
Reacti komponendipõhine arhitektuur soodustab korduvkasutatavust ja hooldatavust, kuid see toob kaasa ka potentsiaali vigade levimiseks ja kogu rakenduse töö häirimiseks. Käsitlemata vead võivad pakkuda kasutajatele ebameeldiva kogemuse, kuvades krüptilisi sõnumeid või isegi rakenduse kokku jooksutades. Veapiirid (Error Boundaries) pakuvad mehhanismi JavaScripti vigade püüdmiseks mis tahes kohas nende alamkomponentide puus, nende vigade logimiseks ja varu-kasutajaliidese kuvamiseks kokku jooksnud komponendipuu asemel. Hästi disainitud veapiiride puu võimaldab teil isoleerida tõrkeid ja pakkuda paremat kasutajakogemust, halvendades sujuvalt teie rakenduse teatud osade talitlust teisi mõjutamata.
Reacti veapiiride mõistmine
React 16-s tutvustatud veapiirid on Reacti komponendid, mis püüavad JavaScripti vigu mis tahes kohas nende alamkomponentide puus, logivad neid vigu ja kuvavad varu-kasutajaliidese kokku jooksnud komponendipuu asemel. Veapiirid püüavad vigu renderdamise ajal, elutsükli meetodites ja kogu alluva puu konstruktorites. On oluline märkida, et nad *ei* püüa vigu järgmistel juhtudel:
- Sündmuste käsitlejad (event handlers) (loe lähemalt allpool)
- AsĂĽnkroonne kood (nt
setTimeoutvõirequestAnimationFrametagasikutsefunktsioonid) - Serveripoolne renderdamine (Server side rendering)
- Vead, mis visatakse veapiiri enda sees (mitte selle alamkomponentides)
Klassikomponent muutub veapiiriks, kui see defineerib ühe (või mõlemad) neist elutsükli meetoditest:
static getDerivedStateFromError(): See meetod kutsutakse välja pärast seda, kui alamkomponent on vea visanud. See saab argumendiks visatud vea ja peaks tagastama väärtuse oleku uuendamiseks.componentDidCatch(): See meetod kutsutakse välja pärast seda, kui alamkomponent on vea visanud. See saab kaks argumenti:error: Visatud viga.info: Objekt, mis sisaldab teavet selle kohta, milline komponent vea viskas.
Lihtne veapiiri näide
Siin on lihtne veapiiri komponent:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Uuenda olekut, et järgmine renderdus näitaks varu-kasutajaliidest.
return { hasError: true };
}
componentDidCatch(error, info) {
// Saate vea logida ka vearaportiteenusesse
console.error("PĂĽĂĽtud viga: ", error, info.componentStack);
//logErrorToMyService(error, info.componentStack);
}
render() {
if (this.state.hasError) {
// Saate renderdada mis tahes kohandatud varu-kasutajaliidese
return <h1>Midagi läks valesti.</h1>;
}
return this.props.children;
}
}
Kasutamine:
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
Veapiiride puu võimsus
Kuigi üksainus veapiir võib kaitsta kogu teie rakendust, hõlmab keerukam lähenemine veapiiride *puu* loomist. See tähendab mitme veapiiri strateegilist paigutamist teie komponendi hierarhia eri tasanditele. See võimaldab teil:
- Isoleerida tõrkeid: Tõrge ühes rakenduse osas ei too tingimata kaasa kogu kasutajaliidese kokkuvarisemist. Ainult konkreetse veapiiriga ümbritsetud osa kuvab varu-kasutajaliidese.
- Pakkuda kontekstipõhiseid varuvariante: Teie rakenduse erinevad osad võivad vajada erinevaid varu-kasutajaliideseid. Näiteks võib tõrkega pildikomponent kuvada kohatäitepildi, samas kui tõrkega andmete pärimise komponent võib kuvada nupu "Proovi uuesti".
- Parandada kasutajakogemust: Veapiire hoolikalt paigutades saate tagada, et teie rakenduse talitlus halveneb sujuvalt, minimeerides kasutaja jaoks häireid.
Veapiiride puu ehitamine: praktiline näide
Vaatleme veebirakendust, mis kuvab kasutajaprofiili. Profiil koosneb mitmest jaotisest:
- Kasutaja teave (nimi, asukoht, bio)
- Profiilipilt
- Hiljutine tegevuste voog
- Jälgijate nimekiri
Saame igaĂĽhe neist jaotistest ĂĽmbritseda oma veapiiriga.
// ErrorBoundary.js (ĂĽlalpool toodud ĂĽldine veapiiri komponent)
import ErrorBoundary from './ErrorBoundary';
function UserProfile() {
return (
<div>
<ErrorBoundary>
<UserInfo />
</ErrorBoundary>
<ErrorBoundary fallbackUI={<img src="/placeholder.png" alt="Kohatäide"/>}>
<ProfilePicture />
</ErrorBoundary>
<ErrorBoundary fallbackUI={<p>Tegevuste laadimine ebaõnnestus. Palun proovige hiljem uuesti.</p>}>
<ActivityFeed />
</ErrorBoundary>
<ErrorBoundary fallbackUI={<p>Jälgijate laadimine ebaõnnestus.</p>}>
<FollowersList />
</ErrorBoundary>
</div>
);
}
Selles näites, kui ProfilePicture komponendi laadimine ebaõnnestub (nt katkise pildi URL-i tõttu), kuvab ainult profiilipildi ala varu-kasutajaliidese (kohatäitepildi). Ülejäänud profiil jääb funktsionaalseks. Samamoodi mõjutab tõrge ActivityFeed komponendis ainult seda jaotist, kuvades teate "Palun proovige hiljem uuesti".
Pange tähele fallbackUI omaduse kasutamist mõnedes ErrorBoundary komponentides. See võimaldab meil kohandada iga jaotise varu-kasutajaliidest, pakkudes kontekstitundlikumat ja kasutajasõbralikumat kogemust.
Täiustatud veapiiride tehnikad
1. Varu-kasutajaliidese kohandamine
Vaikimisi varu-kasutajaliides (nt lihtne teade "Midagi läks valesti") ei pruugi kõikideks stsenaariumiteks piisav olla. Saate kohandada varu-kasutajaliidest, et pakkuda informatiivsemaid teateid, alternatiivseid tegevusi või isegi proovida veast taastuda.
Nagu eelmises näites näidatud, saate kasutada omadusi (props), et edastada kohandatud varu-kasutajaliides ErrorBoundary komponendile:
<ErrorBoundary fallbackUI={<CustomFallbackComponent />}>
<MyComponent />
</ErrorBoundary>
CustomFallbackComponent võib kuvada spetsiifilisema veateate, soovitada veaotsingu samme või pakkuda nuppu "Proovi uuesti".
2. Vigade logimine välistesse teenustesse
Kuigi veapiirid hoiavad ära rakenduse kokkujooksmise, on oluline vigu logida, et saaksite tuvastada ja parandada algpõhjuseid. componentDidCatch meetod on ideaalne koht vigade logimiseks välistesse veajälgimisteenustesse nagu Sentry, Bugsnag või Rollbar.
class ErrorBoundary extends React.Component {
// ...
componentDidCatch(error, info) {
// Logi viga vearaportiteenusesse
logErrorToMyService(error, info.componentStack);
}
// ...
}
Veenduge, et konfigureerite oma veajälgimisteenuse JavaScripti vigade käsitlemiseks ja teile üksikasjaliku teabe pakkumiseks vea kohta, sealhulgas komponendi pinu jälje (stack trace).
Näide Sentry kasutamisega:
import * as Sentry from "@sentry/react";
import { BrowserTracing } from "@sentry/tracing";
Sentry.init({
dsn: "YOUR_SENTRY_DSN",
integrations: [new BrowserTracing()],
// Seadke tracesSampleRate väärtuseks 1.0, et püüda 100%
// tehingutest jõudluse jälgimiseks.
// Soovitame seda väärtust toodangus kohandada
tracesSampleRate: 1.0,
});
class ErrorBoundary extends React.Component {
// ...
componentDidCatch(error, info) {
Sentry.captureException(error, { extra: info });
}
// ...
}
3. Veapiirid ja sündmuste käsitlejad
Nagu varem mainitud, veapiirid *ei* püüa vigu sündmuste käsitlejate sees. Seda seetõttu, et sündmuste käsitlejad käivitatakse asünkroonselt, väljaspool Reacti renderdamise elutsüklit. Vigade käsitlemiseks sündmuste käsitlejates peate kasutama try...catch plokki.
function MyComponent() {
const handleClick = () => {
try {
// Kood, mis võib vea visata
throw new Error("Sündmuse käsitlejas läks midagi valesti!");
} catch (error) {
console.error("Viga sündmuse käsitlejas:", error);
// Kuva kasutajale veateade
alert("Tekkis viga. Palun proovige uuesti.");
}
};
return <button onClick={handleClick}>Vajuta siia</button>;
}
4. Veapiirid ja asĂĽnkroonsed operatsioonid
Sarnaselt ei püüa veapiirid vigu asünkroonsetes operatsioonides nagu setTimeout, setInterval või lubadused (Promises). Nende asünkroonsete operatsioonide sees vigade käsitlemiseks peate kasutama try...catch plokke.
Näide lubadustega (Promises):
function MyComponent() {
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP viga! staatus: ${response.status}`);
}
const data = await response.json();
// Töötle andmeid
console.log(data);
} catch (error) {
console.error("Andmete pärimisel tekkis viga:", error);
// Kuva kasutajale veateade
alert("Andmete pärimine ebaõnnestus. Palun kontrollige oma ühendust.");
}
};
fetchData();
}, []);
return <div>Laen andmeid...</div>;
}
5. Ebaõnnestunud operatsioonide uuesti proovimine
Mõnel juhul võib olla võimalik ebaõnnestunud operatsiooni automaatselt uuesti proovida. Näiteks kui võrgupäring ebaõnnestub ajutise ühenduvusprobleemi tõttu, võiksite rakendada uuestiproovimise mehhanismi eksponentsiaalse ooteajaga.
Saate rakendada uuestiproovimise mehhanismi varu-kasutajaliideses või vea kogenud komponendi sees. Kaaluge teekide nagu axios-retry kasutamist või oma uuestiproovimise loogika rakendamist setTimeout abil.
Näide (lihtne uuesti proovimine):
function RetryComponent({ onRetry }) {
return <button onClick={onRetry}>Proovi uuesti</button>;
}
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, info) {
console.error("PĂĽĂĽtud viga: ", error, info.componentStack);
}
handleRetry = () => {
this.setState({ hasError: false, error: null }, () => {
//Sunni komponenti uuesti renderdama, uuendades olekut
this.forceUpdate();
});
};
render() {
if (this.state.hasError) {
return (
<div>
<h1>Midagi läks valesti.</h1>
<p>{this.state.error?.message}</p>
<RetryComponent onRetry={this.handleRetry} />
</div>
);
}
return this.props.children;
}
}
Veapiiride kasutamise parimad praktikad
- Mähkige terved marsruudid (routes): Kõrgema taseme marsruutide puhul kaaluge kogu marsruudi mähkimist veapiiriga, et püüda kinni kõik ootamatud vead, mis võivad tekkida. See pakub turvavõrku ja takistab kogu rakenduse kokkujooksmist.
- Mähkige kriitilised jaotised: Tuvastage oma rakenduse kõige kriitilisemad jaotised (nt e-poe saidi ostuprotsess) ja mähkige need veapiiridega, et tagada nende vastupidavus vigadele.
- Ärge kasutage veapiire liiga palju: Vältige iga üksiku komponendi mähkimist veapiiriga. See võib lisada tarbetut koormust ja muuta teie koodi raskemini loetavaks. Keskenduge komponentide mähkimisele, mis tõenäoliselt ebaõnnestuvad või on kasutajakogemuse jaoks kriitilised.
- Pakkuge informatiivseid varu-kasutajaliideseid: Varu-kasutajaliides peaks pakkuma kasutajale selget ja abistavat teavet selle kohta, mis valesti läks ja mida nad saavad probleemi lahendamiseks teha. Vältige üldiste veateadete kuvamist, mis ei paku konteksti.
- Logige vigu põhjalikult: Veenduge, et logite kõik veapiiridega püütud vead välisesse veajälgimisteenusesse. See aitab teil kiiresti tuvastada ja parandada algpõhjuseid.
- Testige oma veapiire: Kirjutage ühik- ja integratsiooniteste, et tagada oma veapiiride korrektne toimimine ja oodatud vigade püüdmine. Simuleerige veaolukordi ja kontrollige, kas varu-kasutajaliides kuvatakse õigesti.
- Kaaluge globaalset veakäsitlust: Kuigi veapiirid on suurepärased vigade käsitlemiseks Reacti komponentide sees, peaksite kaaluma ka globaalse veakäsitluse rakendamist, et püüda vigu, mis tekivad väljaspool Reacti puud (nt käsitlemata lubaduste tagasilükkamised).
Globaalsed kaalutlused ja kultuuriline tundlikkus
Globaalsele publikule veapiiride puude kujundamisel on oluline arvestada kultuurilise tundlikkuse ja lokaliseerimisega:
- Lokaliseerimine: Veenduge, et teie varu-kasutajaliidesed on erinevate keelte ja piirkondade jaoks korralikult lokaliseeritud. Kasutage lokaliseerimisteeki nagu
i18nextvõireact-intlveateadete ja muu teksti tõlkimiseks. - Kultuuriline kontekst: Olge varu-kasutajaliideste kujundamisel teadlik kultuurilistest erinevustest. Vältige piltide või sümbolite kasutamist, mis võivad teatud kultuurides olla solvavad või sobimatud. Näiteks käemärk, mida ühes kultuuris peetakse positiivseks, võib teises olla solvav.
- Ajavööndid: Kui teie veateated sisaldavad ajatempleid või muud ajaga seotud teavet, veenduge, et need kuvatakse kasutaja kohalikus ajavööndis.
- Valuutad: Kui teie veateated hõlmavad rahalisi väärtusi, kuvage need kasutaja kohalikus valuutas.
- Juurdepääsetavus: Veenduge, et teie varu-kasutajaliidesed on puuetega kasutajatele juurdepääsetavad. Kasutage sobivaid ARIA atribuute ja järgige juurdepääsetavuse juhiseid, et muuta oma rakendus kõigile kasutatavaks.
- Vearaportitega nõustumine (Opt-In): Olge vearaportite osas läbipaistev. Pakkuge kasutajatele võimalust nõustuda või loobuda vearaportite saatmisest teie serveritesse. Tagage vastavus privaatsusmäärustele nagu GDPR ja CCPA.
Näide (Lokaliseerimine `i18next` abil):
// i18n.js (i18next konfiguratsioon)
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './locales/en/translation.json';
import fr from './locales/fr/translation.json';
i18n
.use(initReactI18next) // edastab i18n-i react-i18next'ile
.init({
resources: {
en: { translation: en },
fr: { translation: fr },
},
lng: 'en', // vaikekeel
fallbackLng: 'en',
interpolation: {
escapeValue: false, // react kaitseb juba xss-i eest
},
});
export default i18n;
// ErrorBoundary.js
import { useTranslation } from 'react-i18next';
function ErrorBoundary(props) {
const { t } = useTranslation();
// ...
render() {
if (this.state.hasError) {
return <h1>{t('error.somethingWentWrong')}</h1>;
}
return this.props.children;
}
}
Kokkuvõte
Reacti veapiiride puud on võimas tööriist robustsete ja vastupidavate rakenduste ehitamiseks. Strateegiliselt paigutades veapiire oma komponendi hierarhia eri tasanditele, saate isoleerida tõrkeid, pakkuda kontekstipõhiseid varuvariante ja parandada üldist kasutajakogemust. Ärge unustage käsitleda vigu sündmuste käsitlejates ja asünkroonsetes operatsioonides, kasutades try...catch plokke. Järgides parimaid praktikaid ning arvestades globaalsete ja kultuuriliste teguritega, saate luua rakendusi, mis on nii usaldusväärsed kui ka kasutajasõbralikud mitmekesisele publikule.
Rakendades hästi disainitud veapiiride puud ja pöörates tähelepanu detailidele, saate oluliselt parandada oma Reacti rakenduste usaldusväärsust ja kasutajakogemust, olenemata sellest, kus teie kasutajad asuvad.