Hrvatski

Ovladajte React Error Boundaries za izgradnju otpornih i korisnički prilagođenih aplikacija. Naučite najbolje prakse, tehnike implementacije i napredne strategije rukovanja pogreškama.

React Error Boundaries: Elegantne tehnike rukovanja pogreškama za robusne aplikacije

U dinamičnom svijetu web razvoja, stvaranje robusnih i korisnički prilagođenih aplikacija je od najveće važnosti. React, popularna JavaScript biblioteka za izgradnju korisničkih sučelja, pruža moćan mehanizam za elegantno rukovanje pogreškama: Error Boundaries. Ovaj sveobuhvatni vodič detaljno razmatra koncept Error Boundaries, istražujući njihovu svrhu, implementaciju i najbolje prakse za izgradnju otpornih React aplikacija.

Razumijevanje potrebe za Error Boundaries

React komponente, kao i svaki kod, podložne su pogreškama. Ove pogreške mogu potjecati iz različitih izvora, uključujući:

Bez odgovarajućeg rukovanja pogreškama, pogreška u React komponenti može srušiti cijelu aplikaciju, što rezultira lošim korisničkim iskustvom. Error Boundaries pružaju način da se te pogreške uhvate i spriječe njihovo širenje prema gore u stablu komponenti, osiguravajući da aplikacija ostane funkcionalna čak i kada pojedinačne komponente zakažu.

Što su React Error Boundaries?

Error Boundaries su React komponente koje hvataju JavaScript pogreške bilo gdje u stablu svoje dječje komponente, zapisuju te pogreške i prikazuju rezervni UI umjesto stabla komponente koje se srušilo. Djeluju kao sigurnosna mreža, sprječavajući da pogreške sruše cijelu aplikaciju.

Ključne karakteristike Error Boundaries:

Implementacija Error Boundaries

Prođimo kroz proces stvaranja osnovne Error Boundary komponente:

1. Stvaranje komponente Error Boundary

Prvo, stvorite novu klasnu komponentu, na primjer, nazvanu ErrorBoundary:


import React from 'react';

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

  static getDerivedStateFromError(error) {
    // Ažurirajte stanje tako da će sljedeće renderiranje prikazati rezervni UI.
    return {
      hasError: true
    };
  }

  componentDidCatch(error, errorInfo) {
    // Možete i zapisati pogrešku u uslugu za izvještavanje o pogreškama
    console.error("Uhvaćena pogreška: ", error, errorInfo);
    // Primjer: logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // Možete prikazati bilo koji prilagođeni rezervni UI
      return (
        <div>
          <h2>Nešto je pošlo po zlu.</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;

Objašnjenje:

2. Korištenje Error Boundary

Da biste koristili Error Boundary, jednostavno omotajte bilo koju komponentu koja bi mogla baciti pogrešku s komponentom ErrorBoundary:


import ErrorBoundary from './ErrorBoundary';

function MyComponent() {
  // Ova komponenta bi mogla baciti pogrešku
  return (
    <ErrorBoundary>
      <PotentiallyBreakingComponent />
    </ErrorBoundary>
  );
}

export default MyComponent;

Ako PotentiallyBreakingComponent baci pogrešku, ErrorBoundary će je uhvatiti, zapisati pogrešku i prikazati rezervni UI.

3. Ilustrativni primjeri s globalnim kontekstom

Razmotrite aplikaciju za e-trgovinu koja prikazuje informacije o proizvodu preuzete s udaljenog poslužitelja. Komponenta, ProductDisplay, odgovorna je za prikazivanje detalja o proizvodu. Međutim, poslužitelj povremeno može vratiti neočekivane podatke, što dovodi do pogrešaka pri renderiranju.


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

function ProductDisplay({ product }) {
  // Simulirajte potencijalnu pogrešku ako product.price nije broj
  if (typeof product.price !== 'number') {
    throw new Error('Neispravna cijena proizvoda');
  }

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

export default ProductDisplay;

Da biste se zaštitili od takvih pogrešaka, omotajte komponentu ProductDisplay s ErrorBoundary:


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

function App() {
  const product = {
    name: 'Primjer proizvoda',
    price: 'Nije broj', // Namjerno netočne podatke
    imageUrl: 'https://example.com/image.jpg'
  };

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

export default App;

U ovom scenariju, jer je product.price namjerno postavljen na niz umjesto na broj, komponenta ProductDisplay će baciti pogrešku. ErrorBoundary će uhvatiti ovu pogrešku, sprječavajući pad cijele aplikacije i prikazati rezervni UI umjesto oštećene komponente ProductDisplay.

4. Error Boundaries u internacionaliziranim aplikacijama

Prilikom izgradnje aplikacija za globalnu publiku, poruke o pogreškama trebaju biti lokalizirane kako bi se pružilo bolje korisničko iskustvo. Error Boundaries se mogu koristiti u kombinaciji s bibliotekama za internacionalizaciju (i18n) za prikaz prevedenih poruka o pogreškama.


// ErrorBoundary.js (s podrškom za i18n)
import React from 'react';
import { useTranslation } from 'react-i18next'; // Pod pretpostavkom da koristite 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("Uhvaćena pogreška: ", 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;

U ovom primjeru koristimo react-i18next za prevođenje naslova i poruke o pogrešci u rezervnom UI-ju. Funkcije t('error.title') i t('error.message') će preuzeti odgovarajuće prijevode na temelju jezika koji je korisnik odabrao.

5. Razmatranja za renderiranje na strani poslužitelja (SSR)

Kada koristite Error Boundaries u aplikacijama renderiranim na strani poslužitelja, ključno je ispravno rukovati pogreškama kako biste spriječili pad poslužitelja. Reactova dokumentacija preporučuje da izbjegavate korištenje Error Boundaries za oporavak od pogrešaka renderiranja na poslužitelju. Umjesto toga, obradite pogreške prije renderiranja komponente ili renderirajte statičnu stranicu s pogreškom na poslužitelju.

Najbolje prakse za korištenje Error Boundaries

Napredne strategije rukovanja pogreškama

1. Mehanizmi ponovnog pokušaja

U nekim slučajevima, možda je moguće oporaviti se od pogreške ponavljanjem operacije koja ju je uzrokovala. Na primjer, ako zahtjev za mrežom ne uspije, možete ga ponoviti nakon kratke odgode. Error Boundaries se mogu kombinirati s mehanizmima ponovnog pokušaja kako bi se osiguralo otpornije korisničko iskustvo.


// 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("Uhvaćena pogreška: ", error, errorInfo);
  }

  handleRetry = () => {
    this.setState(prevState => ({
      hasError: false,
      retryCount: prevState.retryCount + 1,
    }), () => {
      // Ovo prisiljava komponentu da se ponovno renderira. Razmotrite bolje uzorke s kontroliranim rekvizitima.
      this.forceUpdate(); // UPOZORENJE: Koristite s oprezom
      if (this.props.onRetry) {
          this.props.onRetry();
      }
    });
  };

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h2>Nešto je pošlo po zlu.</h2>
          <button onClick={this.handleRetry}>Pokušaj ponovno</button>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundaryWithRetry;

Komponenta ErrorBoundaryWithRetry uključuje gumb za ponovni pokušaj koji, kada se klikne, poništava stanje hasError i ponovno prikazuje dječje komponente. Također možete dodati retryCount kako biste ograničili broj pokušaja. Ovaj pristup može biti posebno koristan za rukovanje prolaznim pogreškama, kao što su privremeni prekidi mreže. Provjerite je li rekvizit `onRetry` obrađen u skladu s tim i ponovno preuzima/ponovno izvršava logiku koja je možda imala pogrešku.

2. Zastavice značajki

Zastavice značajki omogućuju vam dinamičko omogućavanje ili onemogućavanje značajki u vašoj aplikaciji, bez implementacije novog koda. Error Boundaries se mogu koristiti u kombinaciji sa zastavicama značajki za elegantnu degradaciju funkcionalnosti u slučaju pogreške. Na primjer, ako određena značajka uzrokuje pogreške, možete je onemogućiti pomoću zastavice značajke i prikazati poruku korisniku koja označava da značajka privremeno nije dostupna.

3. Uzorak prekidača strujnog kruga

Uzorak prekidača strujnog kruga je uzorak dizajna softvera koji se koristi za sprječavanje da aplikacija ponovljeno pokušava izvršiti operaciju koja će vjerojatno propasti. Djeluje tako da prati stope uspjeha i neuspjeha operacije i, ako stopa neuspjeha premaši određeni prag, „otvara strujni krug“ i sprječava daljnje pokušaje izvršavanja operacije na određeno vremensko razdoblje. To može pomoći u sprječavanju kaskadnih kvarova i poboljšati ukupnu stabilnost aplikacije.

Error Boundaries se mogu koristiti za implementaciju uzorka prekidača strujnog kruga u React aplikacijama. Kada Error Boundary uhvati pogrešku, može povećati brojač neuspjeha. Ako brojač neuspjeha premaši prag, Error Boundary može prikazati poruku korisniku koja označava da značajka privremeno nije dostupna i spriječiti daljnje pokušaje izvršavanja operacije. Nakon određenog vremenskog razdoblja, Error Boundary može „zatvoriti strujni krug“ i ponovno dopustiti pokušaje izvršavanja operacije.

Zaključak

React Error Boundaries su bitan alat za izgradnju robusnih i korisnički prilagođenih aplikacija. Implementacijom Error Boundaries možete spriječiti da pogreške sruše cijelu vašu aplikaciju, pružiti elegantan rezervni UI svojim korisnicima i zapisivati pogreške u usluge nadzora za ispravljanje pogrešaka i analizu. Slijedeći najbolje prakse i napredne strategije navedene u ovom vodiču, možete izgraditi React aplikacije koje su otporne, pouzdane i pružaju pozitivno korisničko iskustvo, čak i u slučaju neočekivanih pogrešaka. Ne zaboravite se usredotočiti na pružanje korisnih poruka o pogreškama koje su lokalizirane za globalnu publiku.

React Error Boundaries: Elegantne tehnike rukovanja pogreškama za robusne aplikacije | MLOG