Lietuvių

Įvaldykite React klaidų ribas (Error Boundaries), kad kurtumėte atsparias ir patogias vartotojui programas. Sužinokite geriausias praktikas, diegimo būdus ir pažangias klaidų valdymo strategijas.

React klaidų ribos (Error Boundaries): Elegantiški klaidų valdymo būdai patikimoms programoms

Dinamiškame svetainių kūrimo pasaulyje ypač svarbu kurti patikimas ir vartotojui patogias programas. React, populiari JavaScript biblioteka, skirta vartotojo sąsajoms kurti, siūlo galingą mechanizmą elegantiškam klaidų valdymui: klaidų ribas (Error Boundaries). Šis išsamus vadovas gilinsis į klaidų ribų koncepciją, nagrinės jų paskirtį, diegimą ir geriausias praktikas kuriant atsparias React programas.

Klaidų ribų (Error Boundaries) poreikio supratimas

React komponentai, kaip ir bet koks kodas, yra pažeidžiami klaidų. Šios klaidos gali kilti iš įvairių šaltinių, įskaitant:

Be tinkamo klaidų valdymo, klaida React komponente gali sugadinti visą programą, o tai lemia prastą vartotojo patirtį. Klaidų ribos (Error Boundaries) suteikia būdą pagauti šias klaidas ir neleisti joms plisti aukštyn komponentų medyje, užtikrinant, kad programa išliktų funkcionali net ir sugedus atskiriems komponentams.

Kas yra React klaidų ribos (Error Boundaries)?

Klaidų ribos (Error Boundaries) yra React komponentai, kurie pagauna JavaScript klaidas bet kurioje savo vaikinių komponentų medžio vietoje, registruoja tas klaidas ir rodo atsarginę vartotojo sąsają (fallback UI) vietoje sugriuvusio komponentų medžio. Jie veikia kaip apsauginis tinklas, neleidžiantis klaidoms sugadinti visos programos.

Pagrindinės klaidų ribų savybės:

Klaidų ribų diegimas

Panagrinėkime pagrindinio klaidų ribos (Error Boundary) komponento kūrimo procesą:

1. Klaidų ribos (Error Boundary) komponento kūrimas

Pirmiausia, sukurkite naują klasių komponentą, pavyzdžiui, pavadintą ErrorBoundary:


import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false
    };
  }

  static getDerivedStateFromError(error) {
    // Atnaujiname būseną, kad kitas atvaizdavimas parodytų atsarginę vartotojo sąsają.
    return {
      hasError: true
    };
  }

  componentDidCatch(error, errorInfo) {
    // Taip pat galite registruoti klaidą klaidų pranešimų tarnyboje
    console.error("Caught error: ", error, errorInfo);
    // Pavyzdys: logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // Galite atvaizduoti bet kokią pasirinktinę atsarginę vartotojo sąsają
      return (
        <div>
          <h2>Kažkas nutiko negerai.</h2>
          <details style={{ whiteSpace: 'pre-wrap' }}>
            {this.state.error && this.state.error.toString()}
            <br />
            {this.state.errorInfo.componentStack}
          </details>
        </div>
      );
    }

    return this.props.children; 
  }
}

export default ErrorBoundary;

Paaiškinimas:

2. Klaidų ribos naudojimas

Norėdami naudoti klaidų ribą, tiesiog apgaubkite bet kurį komponentą, kuris gali išmesti klaidą, su ErrorBoundary komponentu:


import ErrorBoundary from './ErrorBoundary';

function MyComponent() {
  // Šis komponentas gali išmesti klaidą
  return (
    <ErrorBoundary>
      <PotentiallyBreakingComponent />
    </ErrorBoundary>
  );
}

export default MyComponent;

Jei PotentiallyBreakingComponent išmes klaidą, ErrorBoundary ją pagaus, užregistruos klaidą ir atvaizduos atsarginę vartotojo sąsają.

3. Iliustratyvūs pavyzdžiai bendrame kontekste

Įsivaizduokite el. prekybos programą, rodančią produkto informaciją, gautą iš nuotolinio serverio. Komponentas ProductDisplay yra atsakingas už produkto detalių atvaizdavimą. Tačiau serveris kartais gali grąžinti netikėtus duomenis, dėl ko kyla atvaizdavimo klaidų.


// ProductDisplay.js
import React from 'react';

function ProductDisplay({ product }) {
  // Imituojame galimą klaidą, jei product.price nėra skaičius
  if (typeof product.price !== 'number') {
    throw new Error('Neteisinga produkto kaina');
  }

  return (
    <div>
      <h2>{product.name}</h2>
      <p>Kaina: {product.price}</p>
      <img src={product.imageUrl} alt={product.name} />
    </div>
  );
}

export default ProductDisplay;

Norėdami apsisaugoti nuo tokių klaidų, apgaubkite ProductDisplay komponentą su ErrorBoundary:


// App.js
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import ProductDisplay from './ProductDisplay';

function App() {
  const product = {
    name: 'Pavyzdinis produktas',
    price: 'Ne skaičius', // Tyčia neteisingi duomenys
    imageUrl: 'https://example.com/image.jpg'
  };

  return (
    <div>
      <ErrorBoundary>
        <ProductDisplay product={product} />
      </ErrorBoundary>
    </div>
  );
}

export default App;

Šiame scenarijuje, kadangi product.price yra tyčia nustatyta kaip eilutė, o ne skaičius, ProductDisplay komponentas išmes klaidą. ErrorBoundary pagaus šią klaidą, neleisdamas visai programai sugriūti, ir vietoj neveikiančio ProductDisplay komponento parodys atsarginę vartotojo sąsają.

4. Klaidų ribos internacionalizuotose programose

Kuriant programas pasaulinei auditorijai, klaidų pranešimai turėtų būti lokalizuoti, kad būtų užtikrinta geresnė vartotojo patirtis. Klaidų ribos gali būti naudojamos kartu su internacionalizacijos (i18n) bibliotekomis, norint rodyti išverstus klaidų pranešimus.


// ErrorBoundary.js (su i18n palaikymu)
import React from 'react';
import { useTranslation } from 'react-i18next'; // Darome prielaidą, kad naudojate react-i18next

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
    };
  }

  static getDerivedStateFromError(error) {
    return {
      hasError: true,
      error: error,
    };
  }

  componentDidCatch(error, errorInfo) {
    console.error("Caught error: ", error, errorInfo);
    this.setState({errorInfo: errorInfo});
  }

  render() {
    if (this.state.hasError) {
      return (
        <FallbackUI error={this.state.error} errorInfo={this.state.errorInfo}/>
      );
    }

    return this.props.children;
  }
}

const FallbackUI = ({error, errorInfo}) => {
  const { t } = useTranslation();

  return (
    <div>
      <h2>{t('error.title')}</h2>
      <p>{t('error.message')}</p>
      <details style={{ whiteSpace: 'pre-wrap' }}>
        {error && error.toString()}<br />
        {errorInfo?.componentStack}
      </details>
    </div>
  );
}


export default ErrorBoundary;

Šiame pavyzdyje mes naudojame react-i18next, kad išverstume klaidos pavadinimą ir pranešimą atsarginėje vartotojo sąsajoje. Funkcijos t('error.title') ir t('error.message') gaus atitinkamus vertimus pagal vartotojo pasirinktą kalbą.

5. Aspektai, susiję su serverio pusės atvaizdavimu (SSR)

Naudojant klaidų ribas serverio pusėje atvaizduojamose programose, labai svarbu tinkamai tvarkyti klaidas, kad serveris nenustotų veikti. React dokumentacijoje rekomenduojama vengti naudoti klaidų ribas atvaizdavimo klaidoms serveryje taisyti. Vietoj to, tvarkykite klaidas prieš atvaizduodami komponentą arba atvaizduokite statinį klaidos puslapį serveryje.

Geriausios klaidų ribų naudojimo praktikos

Pažangios klaidų valdymo strategijos

1. Pakartotinio bandymo mechanizmai

Kai kuriais atvejais gali būti įmanoma atsigauti po klaidos pakartojant operaciją, kuri ją sukėlė. Pavyzdžiui, jei tinklo užklausa nepavyksta, galite ją pakartoti po trumpos pauzės. Klaidų ribos gali būti derinamos su pakartotinio bandymo mechanizmais, siekiant suteikti atsparesnę vartotojo patirtį.


// ErrorBoundaryWithRetry.js
import React from 'react';

class ErrorBoundaryWithRetry extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false,
      retryCount: 0,
    };
  }

  static getDerivedStateFromError(error) {
    return {
      hasError: true,
    };
  }

  componentDidCatch(error, errorInfo) {
    console.error("Caught error: ", error, errorInfo);
  }

  handleRetry = () => {
    this.setState(prevState => ({
      hasError: false,
      retryCount: prevState.retryCount + 1,
    }), () => {
      // Tai priverčia komponentą persikrauti. Apsvarstykite geresnius šablonus su valdomais „props“.
      this.forceUpdate(); // ĮSPĖJIMAS: Naudokite atsargiai
      if (this.props.onRetry) {
          this.props.onRetry();
      }
    });
  };

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h2>Kažkas nutiko negerai.</h2>
          <button onClick={this.handleRetry}>Bandyti dar kartą</button>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundaryWithRetry;

Komponentas ErrorBoundaryWithRetry turi pakartotinio bandymo mygtuką, kuris, jį paspaudus, atstato hasError būseną ir iš naujo atvaizduoja vaikinius komponentus. Taip pat galite pridėti retryCount, kad apribotumėte bandymų skaičių. Šis metodas gali būti ypač naudingas tvarkant laikinas klaidas, pvz., laikinus tinklo sutrikimus. Įsitikinkite, kad onRetry savybė (prop) yra tinkamai apdorojama ir iš naujo gauna duomenis/vykdo logiką, kuri galėjo sukelti klaidą.

2. Funkcionalumo vėliavėlės (Feature Flags)

Funkcionalumo vėliavėlės leidžia dinamiškai įjungti arba išjungti funkcijas jūsų programoje, nediegiant naujo kodo. Klaidų ribos gali būti naudojamos kartu su funkcionalumo vėliavėlėmis, siekiant laipsniškai sumažinti funkcionalumą klaidos atveju. Pavyzdžiui, jei tam tikra funkcija sukelia klaidų, galite ją išjungti naudodami funkcionalumo vėliavėlę ir parodyti vartotojui pranešimą, nurodantį, kad funkcija laikinai nepasiekiama.

3. Grandinės pertraukiklio šablonas (Circuit Breaker Pattern)

Grandinės pertraukiklio šablonas yra programinės įrangos projektavimo šablonas, naudojamas siekiant išvengti, kad programa nuolat bandytų vykdyti operaciją, kuri greičiausiai nepavyks. Jis veikia stebėdamas operacijos sėkmės ir nesėkmės rodiklius ir, jei nesėkmių lygis viršija tam tikrą ribą, „atidaro grandinę“ ir tam tikrą laiką neleidžia toliau bandyti vykdyti operacijos. Tai gali padėti išvengti kaskadinių gedimų ir pagerinti bendrą programos stabilumą.

Klaidų ribos gali būti naudojamos grandinės pertraukiklio šablonui įgyvendinti React programose. Kai klaidų riba pagauna klaidą, ji gali padidinti nesėkmių skaitiklį. Jei nesėkmių skaitiklis viršija ribą, klaidų riba gali parodyti vartotojui pranešimą, nurodantį, kad funkcija laikinai nepasiekiama, ir užkirsti kelią tolesniems bandymams vykdyti operaciją. Po tam tikro laiko klaidų riba gali „uždaryti grandinę“ ir vėl leisti bandyti vykdyti operaciją.

Išvada

React klaidų ribos (Error Boundaries) yra esminis įrankis kuriant patikimas ir vartotojui draugiškas programas. Įdiegę klaidų ribas, galite apsaugoti visą programą nuo sugriuvimo, pateikti vartotojams elegantišką atsarginę vartotojo sąsają ir registruoti klaidas stebėjimo tarnybose derinimo ir analizės tikslais. Laikydamiesi šiame vadove aprašytų geriausių praktikų ir pažangių strategijų, galite kurti React programas, kurios yra atsparios, patikimos ir suteikia teigiamą vartotojo patirtį net ir susidūrus su netikėtomis klaidomis. Nepamirškite sutelkti dėmesį į naudingų klaidų pranešimų, lokalizuotų pasaulinei auditorijai, teikimą.