Norsk

Mestre React Error Boundaries for å bygge robuste og brukervennlige applikasjoner. Lær beste praksis, implementeringsteknikker og avanserte strategier for feilhåndtering.

React Error Boundaries: Teknikker for elegant feilhåndtering for robuste applikasjoner

I den dynamiske verdenen av webutvikling er det avgjørende å skape robuste og brukervennlige applikasjoner. React, et populært JavaScript-bibliotek for å bygge brukergrensesnitt, tilbyr en kraftig mekanisme for å håndtere feil på en elegant måte: Error Boundaries. Denne omfattende guiden dykker ned i konseptet Error Boundaries, og utforsker deres formål, implementering og beste praksis for å bygge robuste React-applikasjoner.

Forstå behovet for Error Boundaries

React-komponenter, som all annen kode, er utsatt for feil. Disse feilene kan stamme fra ulike kilder, inkludert:

Uten riktig feilhåndtering kan en feil i en React-komponent krasje hele applikasjonen, noe som resulterer i en dårlig brukeropplevelse. Error Boundaries gir en måte å fange opp disse feilene og forhindre dem i å forplante seg oppover i komponenttreet, og sikrer dermed at applikasjonen forblir funksjonell selv når individuelle komponenter feiler.

Hva er React Error Boundaries?

Error Boundaries er React-komponenter som fanger opp JavaScript-feil hvor som helst i sitt barnekomponenttre, logger disse feilene, og viser et reserve-brukergrensesnitt (fallback UI) i stedet for komponenttreet som krasjet. De fungerer som et sikkerhetsnett, og forhindrer at feil krasjer hele applikasjonen.

Nøkkelegenskaper for Error Boundaries:

Implementering av Error Boundaries

La oss gå gjennom prosessen med å lage en grunnleggende Error Boundary-komponent:

1. Lage Error Boundary-komponenten

Først, lag en ny klassekomponent, for eksempel kalt ErrorBoundary:


import React from 'react';

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

  static getDerivedStateFromError(error) {
    // Oppdater state slik at neste render vil vise reserve-UI-et.
    return {
      hasError: true
    };
  }

  componentDidCatch(error, errorInfo) {
    // Du kan også logge feilen til en feilrapporteringstjeneste
    console.error("Caught error: ", error, errorInfo);
    // Eksempel: loggFeilTilMinTjeneste(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // Du kan rendre hvilket som helst tilpasset reserve-UI
      return (
        <div>
          <h2>Noe gikk galt.</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;

Forklaring:

2. Bruke Error Boundary

For å bruke Error Boundary, pakk enkelt og greit inn enhver komponent som kan kaste en feil med ErrorBoundary-komponenten:


import ErrorBoundary from './ErrorBoundary';

function MyComponent() {
  // Denne komponenten kan kaste en feil
  return (
    <ErrorBoundary>
      <PotentiallyBreakingComponent />
    </ErrorBoundary>
  );
}

export default MyComponent;

Hvis PotentiallyBreakingComponent kaster en feil, vil ErrorBoundary fange den opp, logge feilen og rendre reserve-UI-et.

3. Illustrerende eksempler med global kontekst

Tenk deg en e-handelsapplikasjon som viser produktinformasjon hentet fra en ekstern server. En komponent, ProductDisplay, er ansvarlig for å rendre produktdetaljer. Serveren kan imidlertid av og til returnere uventede data, noe som fører til render-feil.


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

function ProductDisplay({ product }) {
  // Simuler en potensiell feil hvis product.price ikke er et tall
  if (typeof product.price !== 'number') {
    throw new Error('Ugyldig produktpris');
  }

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

export default ProductDisplay;

For å beskytte mot slike feil, pakk inn ProductDisplay-komponenten med en ErrorBoundary:


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

function App() {
  const product = {
    name: 'Eksempelprodukt',
    price: 'Ikke et tall', // Bevisst ukorrekt data
    imageUrl: 'https://example.com/image.jpg'
  };

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

export default App;

I dette scenarioet, fordi product.price er bevisst satt til en streng i stedet for et tall, vil ProductDisplay-komponenten kaste en feil. ErrorBoundary vil fange opp denne feilen, forhindre at hele applikasjonen krasjer, og vise reserve-UI-et i stedet for den ødelagte ProductDisplay-komponenten.

4. Error Boundaries i internasjonaliserte applikasjoner

Når man bygger applikasjoner for et globalt publikum, bør feilmeldinger lokaliseres for å gi en bedre brukeropplevelse. Error Boundaries kan brukes sammen med internasjonaliseringsbiblioteker (i18n) for å vise oversatte feilmeldinger.


// ErrorBoundary.js (med i18n-støtte)
import React from 'react';
import { useTranslation } from 'react-i18next'; // Forutsatt at du bruker 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;

I dette eksempelet bruker vi react-i18next til å oversette feiltittelen og meldingen i reserve-UI-et. Funksjonene t('error.title') og t('error.message') vil hente de passende oversettelsene basert på brukerens valgte språk.

5. Vurderinger for Server-Side Rendering (SSR)

Når man bruker Error Boundaries i server-side-rendrede applikasjoner, er det avgjørende å håndtere feil på en passende måte for å forhindre at serveren krasjer. Reacts dokumentasjon anbefaler at du unngår å bruke Error Boundaries for å hente deg inn fra render-feil på serveren. I stedet bør du håndtere feil før du rendrer komponenten, eller rendre en statisk feilside på serveren.

Beste praksis for bruk av Error Boundaries

Avanserte strategier for feilhåndtering

1. Gjenforsøksmekanismer

I noen tilfeller kan det være mulig å hente seg inn fra en feil ved å prøve operasjonen som forårsaket den på nytt. For eksempel, hvis en nettverksforespørsel mislykkes, kan du prøve den på nytt etter en kort forsinkelse. Error Boundaries kan kombineres med gjenforsøksmekanismer for å gi en mer robust brukeropplevelse.


// 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,
    }), () => {
      // Dette tvinger komponenten til å re-rendre. Vurder bedre mønstre med kontrollerte props.
      this.forceUpdate(); // ADVARSEL: Brukes med forsiktighet
      if (this.props.onRetry) {
          this.props.onRetry();
      }
    });
  };

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h2>Noe gikk galt.</h2>
          <button onClick={this.handleRetry}>Prøv igjen</button>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundaryWithRetry;

ErrorBoundaryWithRetry-komponenten inkluderer en "Prøv igjen"-knapp som, når den klikkes, nullstiller hasError-state og re-rendrer barnekomponentene. Du kan også legge til en retryCount for å begrense antall gjenforsøk. Denne tilnærmingen kan være spesielt nyttig for å håndtere forbigående feil, som midlertidige nettverksbrudd. Sørg for at `onRetry`-prop blir håndtert tilsvarende og henter/utfører logikken som kan ha feilet på nytt.

2. Funksjonsflagg

Funksjonsflagg lar deg aktivere eller deaktivere funksjoner i applikasjonen din dynamisk, uten å deploye ny kode. Error Boundaries kan brukes sammen med funksjonsflagg for å elegant degradere funksjonalitet i tilfelle en feil. For eksempel, hvis en bestemt funksjon forårsaker feil, kan du deaktivere den ved hjelp av et funksjonsflagg og vise en melding til brukeren som indikerer at funksjonen er midlertidig utilgjengelig.

3. Circuit Breaker-mønsteret

Circuit breaker-mønsteret er et programvaredesignmønster som brukes for å forhindre en applikasjon i å gjentatte ganger prøve å utføre en operasjon som sannsynligvis vil mislykkes. Det fungerer ved å overvåke suksess- og feilratene for en operasjon, og hvis feilraten overstiger en viss terskel, "åpner det kretsen" og forhindrer ytterligere forsøk på å utføre operasjonen i en viss periode. Dette kan bidra til å forhindre kaskadefeil og forbedre den generelle stabiliteten til applikasjonen.

Error Boundaries kan brukes til å implementere circuit breaker-mønsteret i React-applikasjoner. Når en Error Boundary fanger en feil, kan den øke en feilteller. Hvis feiltelleren overstiger en terskel, kan Error Boundary vise en melding til brukeren som indikerer at funksjonen er midlertidig utilgjengelig og forhindre ytterligere forsøk på å utføre operasjonen. Etter en viss periode kan Error Boundary "lukke kretsen" og tillate forsøk på å utføre operasjonen igjen.

Konklusjon

React Error Boundaries er et essensielt verktøy for å bygge robuste og brukervennlige applikasjoner. Ved å implementere Error Boundaries kan du forhindre at feil krasjer hele applikasjonen, gi et elegant reserve-UI til brukerne dine, og logge feil til overvåkingstjenester for feilsøking og analyse. Ved å følge beste praksis og de avanserte strategiene som er skissert i denne guiden, kan du bygge React-applikasjoner som er robuste, pålitelige og leverer en positiv brukeropplevelse, selv i møte med uventede feil. Husk å fokusere på å gi nyttige feilmeldinger som er lokalisert for et globalt publikum.