Come utilizzare i limiti di errore di React per catturare gli arresti anomali

0
137

I limiti di errore di React consentono di rilevare gli errori JavaScript che si verificano nei componenti figlio. Qualsiasi errore non gestito originato al di sotto della posizione dell'albero del limite verrà rilevato, impedendo il verificarsi di un arresto anomalo.

È possibile visualizzare la propria interfaccia utente di fallback dopo che un limite di errore rileva un errore. Ciò consente di comunicare con garbo il problema all'utente. Saranno in grado di continuare a utilizzare il resto della tua interfaccia senza subire un blocco completo della scheda.

Creazione di limiti di errore

Qualsiasi reazione componente di classe può diventare un limite di errore. Devi solo impostare uno dei seguenti metodi del ciclo di vita:

  • componentDidCatch(error)– Questo metodo di istanza verrà chiamato ogni volta che il componente rileva un errore. Puoi utilizzarlo per segnalare l'errore a un servizio di analisi o monitoraggio.
  • static getDerivedStateFromError(error) – Questo metodo statico può essere utilizzato per aggiornare lo stato del componente dopo che si è verificato un errore. Ecco come visualizzare un'interfaccia utente di fallback.

Ecco come appaiono i due metodi in uso:

componentDidCatch()

class MyComponent estende React.Component {   componenteDidCatch(errore) { //usa il framework di reporting personalizzato logErrorToAnalytics(error); this.props.onError(error); }   }

Utilizzando componentDidCatch(), il tuo componente può segnalare l'errore nel modo che ritiene opportuno. Poiché è un metodo di istanza, puoi anche passarlo nell'albero dei componenti tramite props.

getDerivedStateFromError(error)

class MyComponent estende React.Component {   stato = {errore: null};   rendere() { return <h1>{!this.state.error ? "Ciao" : "Errore"}</h1>; }   statico getDerivedStateFromError(error) { restituisce {errore}; }   }

getDerivedStateFromError() riceve anche l'oggetto errore JavaScript. Deve restituire un oggetto che descrive la trasformazione dello stato da applicare al tuo componente.

React passerà l'oggetto restituito a setState(). In questo esempio, il valore della chiave di errore nello stato del componente verrà impostato sull'oggetto errore rilevato. Ciò comporterà la modifica dell'output visualizzato in Error invece del testo Hello standard.

Quale metodo utilizzare?

Se i due i metodi di confine sembrano simili, è perché lo sono! Tecnicamente, puoi definire uno o entrambi questi metodi e ottenere comunque gli stessi risultati – componentDidCatch() potrebbe chiamare setState() per aggiornare lo stato del tuo componente e getDerivedStateFromError() potrebbe chiamare un servizio di monitoraggio esterno per segnalare gli errori che cattura.

La differenza sta nella fase in cui viene colto l'errore. componentDidCatch() cattura gli errori nella fase di commit, dopo che React ha aggiornato il DOM. getDerivedStateFromError() verrà chiamato durante la fase di rendering, prima che React aggiorni il DOM del browser.

Questa sottigliezza dei tempi spiega perché getDerivedStateFromError() viene generalmente utilizzato per passare all'interfaccia utente di fallback. Quando si verifica un errore grave, l'atto di aggiornare il DOM potrebbe provocare ulteriori errori se la tua app è stata lasciata in uno stato incoerente. L'aggiornamento dello stato prima che si verifichi l'aggiornamento del DOM garantisce il rendering immediato dell'interfaccia utente di fallback.

Individuazione dei limiti di errore

Sei libero di utilizzare i limiti di errore ovunque ritieni opportuno. È buona norma utilizzare più limiti di errore. Aggiungi un limite di errore per ogni livello principale della tua interfaccia utente. Ciò ti consente di isolare gli errori nel contenuto della pagina dalla shell dell'applicazione, quindi un arresto anomalo in un percorso non elimina la barra di navigazione.

Ecco una semplice gerarchia di componenti:

esporta cost () => ( <App> <Intestazione /> <Router /> <Piè di pagina /> </App> );

In questa applicazione, il componente App è un semplice wrapper che gestisce lo stato di primo livello. Intestazione esegue il rendering di una barra di navigazione e Piè di pagina visualizza la barra inferiore. Il contenuto della pagina principale – dove è più probabile che si verifichino arresti anomali – viene caricato dinamicamente dal Router, in base all'URL corrente.

Per impostazione predefinita, un arresto anomalo all'interno dei figli del router mette fuori uso l'intero sito. Posizionando un limite di errore attorno al router, gli errori che si verificano all'interno del componente possono essere gestiti con garbo. L'intestazione e il piè di pagina rimangono utilizzabili mentre il contenuto della pagina principale viene sostituito con un messaggio di fallback.

L'app richiede almeno un altro limite di errore. Il wrapping dei figli di App garantisce che gli errori che si verificano all'interno dell'intestazione o del piè di pagina possano essere rilevati. In questa situazione, potrebbe essere accettabile sostituire l'intera interfaccia utente con un messaggio di errore a pagina intera.

Ecco la struttura del componente sottoposta a refactoring:

class ErrorBoundary estende React.Component {   stato = {errore: null};   rendere() { se (!this.state.error) restituisce this.props.children; altrimenti ritorna <h1>Errore!</h1>; }   statico getDerivedStateFromError(error) { restituisce {errore}; }   }   esportazione cost () => ( <App> <Limite errore> <Intestazione> <Limite errore> <Router /> </ErrorBoundary> <Piè di pagina /> </ErrorBoundary> </App> );

Abbiamo astratto la logica del limite di errore in un componente riutilizzabile. Ora possiamo avvolgere ErrorBoundary attorno a tutti i componenti che dovrebbero essere isolati dai loro genitori. Ricorda che non devi creare un componente del limite di errore – per applicazioni semplici o un componente dell'interfaccia utente specifico, puoi aggiungere gli hook del ciclo di vita direttamente in una classe di componenti.

Limiti dei limiti di errore

I limiti di errore hanno alcune importanti limitazioni di cui dovresti essere a conoscenza. Sono in grado di rilevare la maggior parte degli errori JavaScript non gestiti, ma alcuni non verranno rilevati.

I limiti di errore non intercettano gli errori che si verificano nei metodi del gestore eventi. Il codice del gestore eventi non influisce sul processo di rendering di React, quindi il framework può ancora eseguire il rendering dei componenti. Poiché gli errori del gestore di eventi non provocheranno un'interfaccia utente danneggiata o lo smontaggio di componenti, React non tenta di intercettarli.

Se devi rispondere agli errori nei tuoi gestori di eventi, devi usare un normale blocco try/catch. Esegui un aggiornamento dello stato nell'istruzione catch per portare l'interfaccia utente in uno stato di errore.

class MyComponent estende React.Component {   stato = {errore: null};   handleClick = () => { prova { faiqualcosa(); } cattura (errore) { this.setState({error}); } }   rendere() { se (this.state.error) return <p>Errore!</p>; else return <button onClick={this.handleClick}>Invia</button> }   }

A parte i gestori di eventi, i limiti di errore non possono rilevare gli errori che si verificano nel codice asincrono. Se stai utilizzando Promises, async/await o setTimeout(), assicurati di utilizzare i blocchi try/catch/Promise.catch() per rilevare eventuali errori che potrebbero verificarsi.

Un comune malinteso sui limiti degli errori riguarda l'albero che monitorano. Possono solo rilevare gli errori che si verificano più in profondità nell'albero. I limiti di errore non rilevano gli errori generati dal componente del limite stesso.

default di esportazione () => ( <App> //Gli errori non verranno rilevati <ErrorBoundary> //Gli errori non verranno rilevati <Router /> //Gli errori generati qui verranno rilevati </ErrorBoundary> </App> );

Ogni limite di errore deve avvolgere i componenti che potrebbero generare un errore.

Infine, solo i componenti basati sulla classe possono essere limiti di errore. Attualmente non esiste alcun meccanismo per consentire a un componente funzionale di diventare un limite di errore. Se stai lavorando in una base di codice funzionale, dovresti creare un componente di limite di errore riutilizzabile come quello mostrato sopra. Puoi quindi avvolgere i tuoi componenti con esso ogni volta che hai bisogno di un limite di errore.

Conclusione

I limiti di errore portano JavaScript’catch a React's 8217; modello di rendering dichiarativo. Ti consentono di isolare parti dell'interfaccia utente del tuo sito, in modo che un arresto anomalo in un componente non influisca sui suoi fratelli.

Dovresti valutare l'interfaccia utente della tua app per identificare i punti critici sezioni. Posiziona strategicamente i limiti degli errori per impedire a un errore non gestito di smontare l'intero albero dei componenti. È molto più probabile che gli utenti accettino un “qualcosa’è andato storto” di uno schermo bianco che ha bisogno di essere rinfrescato.