Ich verfolge derzeit die React JS-Dokumentation und bin auf ein Problem gestoßen, bei dem die Fehlergrenzen nicht wie erwartet funktionieren. Ich habe versucht, das in dem von den Dokumenten bereitgestellten CodePen gezeigte Beispiel und einige andere einfache Beispiele, die ich im Internet gefunden habe, zu replizieren, aber es funktioniert bei mir nicht genauso wie in der Demo, und ich habe Probleme zu verstehen warum.
Das genaue Problem ist, dass der Fehler zweimal ausgelöst wird, da die BuggyCounter-Komponente eine zusätzliche Zeit gerendert wird. Ich verstehe nicht, warum die Komponente ein zweites Mal gerendert wird.
Bitte schauen Sie sich dieses minimale Beispiel an.
import React, { Component } from 'react';
function App() {
return (
<ErrorHandler>
<BuggyCounter />
</ErrorHandler>
);
}
class ErrorHandler extends Component {
constructor(props) {
super(props);
this.state = {
error: false,
errorInfo: null
}
}
componentDidCatch(error, errorInfo) {
this.setState({ error, errorInfo });
}
render() {
console.log('rendering ErrorHandler. ' + (this.state.error ? "error" : "no error"));
if(this.state.error) {
return <p>Error</p>
}
return this.props.children;
}
}
class BuggyCounter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
}
handleClick = () => {
this.setState(({ counter }) => ({
counter: counter + 1
}));
};
render() {
console.log('rendering BuggyCounter. count: ' + this.state.counter);
if (this.state.counter === 5) {
throw new Error('I crashed!');
}
return <h1 onClick={this.handleClick}>{this.state.counter}</h1>
}
}
export default App;
Die BuggyCounter-Komponente wird durch das <p>
Tag ersetzt, das "Fehler" (was der gewünschte Effekt ist) darstellt, jedoch nur für einen Moment. Unmittelbar danach wird die Standardfehlerseite angezeigt, wodurch der Zweck der Fehlergrenzen aufgehoben wird.
Hier ist meine Konsole:
Ich würde mich über Informationen zu diesem Thema freuen.
Vorübergehende Auflösung:
Es ist keine Antwort auf meine Frage, aber eine Möglichkeit, das redundante Rendern zu verhindern, besteht darin, den Fehler von componentDidUpdate
statt zu werfen render
.
render() {
console.log('rendering BuggyCounter. count: ' + this.state.counter);
return <h1 onClick={this.handleClick}>{this.state.counter}</h1>
}
componentDidUpdate() {
if(this.state.counter === 5)
throw new Error('I crashed');
}
componentDidCatch
Sie sehen, dass der Fehler zweimal ausgelöst wird, aber nurcomponenDidCatch
einmal übergeben wird.Antworten:
Bearbeiten 2:
Nun, das Problem liegt in der Reaktionsversion
16.12.0
. Wenn Sie es ändern,16.0.0
wird es nicht zweimal neu gerendert. Sie können dies in dieser Codesandbox testen, indem Sie die Reaktionsversion ändern.Dies ist ein gutes Problem, das Sie bei React Github hinzufügen sollten.
Wahrscheinlich ist etwas intern in React Core Code. Abhängig von Ihrer Version wird es also zweimal oder nur einmal gerendert.
Bearbeiten:
Warum wird die Komponente erneut gerendert? Keine Ahnung.
Die Fehlerseite wird jedoch nur im Entwicklungsmodus angezeigt , sodass Sie
componentDidCatch
arbeiten.Alte / schlechte Antwort
Der
only for a moment
Teil ist nicht wahr. Die Fehlerseite ist eigentlich nur für die Entwicklung gedacht. Wenn Sie sie im Produktionsmodus ausführen, wird sie nicht angezeigt.Und wie Sie in meinem Beispiel sehen können , wird beim Schließen der Fehlerseite die Fehlerkomponente angezeigt.
Dies wird in dieser Antwort erklärt .
In der von React Docs bereitgestellten Demoversion wird die Fehlerseite aufgrund der Konfiguration nicht angezeigt, nicht der Code selbst. Ihr Code funktioniert einwandfrei. Schließen Sie einfach die Fehlerseite und sehen Sie die Ergebnisse.
quelle
BuggyCounter
muss zweimal gerendert werden, wennstate.counter === 5
im Protokoll zweimal "Rendering BuggyCounter. Count: 5" angezeigt wird. Ich glaube, Sie haben erklärt, warumErrorHandler
eine zusätzliche Zeit gerendert wird.BuggyCounter
nach dem Auslösen eines Fehlers ein zusätzliches Rendern durchgeführt wird.componentDidCatch
. Statusänderungen rendern Ihre Komponente erneut.ErrorHandler
es wieder gerendert. Das ist nicht meine Frage. Wenn Sie sich das Protokoll ansehen,BuggyCounter
wird es eine zusätzliche Zeit gerendert, bevorErrorHandler
es aufgrund einer Statusänderung erneut gerendert wird.