Actualmente estoy siguiendo junto con la documentación de React JS y he encontrado un problema con los límites de error que no funcionan como se esperaba. He intentado replicar el ejemplo que se muestra en el CodePen proporcionado por los documentos, y algunos otros ejemplos simples que he encontrado en Internet, sin embargo, no funciona igual para mí que en la demostración y estoy luchando para entender por qué.
El problema exacto es que el error se produce dos veces porque el componente BuggyCounter se procesa un tiempo adicional. No entiendo por qué el componente está desgarrando por segunda vez.
Por favor, eche un vistazo a este ejemplo mínimo.
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;
El componente BuggyCounter se está reemplazando con la <p>
etiqueta que muestra "Error" (que es el efecto deseado), pero solo por un momento. Inmediatamente después de eso, se muestra la página de error predeterminada, lo que anula el propósito de los límites de error.
Aquí está mi consola:
Agradecería cualquier información que pudiera proporcionar sobre este tema.
Resolución temporal:
No es una respuesta a mi pregunta, pero una forma de evitar el renderizado redundante es arrojar el error en componentDidUpdate
lugar de hacerlo 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
verá que arroja el error dos veces, pero solo pasacomponenDidCatch
una vez.Respuestas:
Edición 2:
Bueno, el problema está en la versión de reacción
16.12.0
, si lo cambia a16.0.0
, no volverá a aparecer dos veces. Puede probar esto en esta caja de códigos cambiando la versión de reacción.Este es un buen tema para agregar en react github.
Probablemente es algo interno en el código del núcleo de reacción. Entonces, dependiendo de su versión, se renderizará dos veces o solo una vez.
Editar:
¿Por qué el componente se retrae? Ni idea.
Pero, la página de error solo se muestra en modo de desarrollo , por lo que
componentDidCatch
está funcionando.Respuesta anterior / mala
La
only for a moment
parte no es verdad. La página de error es en realidad solo para desarrollo, si la ejecuta en modo de producción, no se mostrará.Y como puede ver en mi ejemplo , si cierra la página de error, verá el componente de error.
Esto se explica en esta respuesta .
Entonces, en la versión de demostración proporcionada por react docs, no muestra la página de error debido a su configuración, no al código en sí. Su código funciona bien, solo cierre la página de error y vea los resultados.
fuente
BuggyCounter
debe procesar dos veces cuandostate.counter === 5
el registro muestra "Rendering BuggyCounter. Count: 5" dos veces. Creo que ha explicado por quéErrorHandler
se le presta un tiempo extra.BuggyCounter
está realizando un renderizado adicional después de arrojar un error.componentDidCatch
. Los cambios de estado le devolverán su componente.ErrorHandler
se vuelve a procesar. Esa no es mi pregunta. Si observa el registro,BuggyCounter
se procesa un tiempo adicional antes deErrorHandler
volver a representarse debido a un cambio de estado.