React - componente DidCatch no captura errores lanzados por componente infantil
Tengo un componente de clase padre con componentDidCatch
método que me gustaría utilizar para registrar errores de frontend a backend.
componentDidCatch(error, errorInfo) {
// Catch errors in any components below and log error message
console.log(error)
console.log(errorInfo)
this.errorLoggGateway.loggError(`${error.toString()}, ${errorInfo.componentStack}`);
}
También he implementado mi propio onUnhandledRejection
método que escucha unhandledrejection
eventos:
componentDidMount() {
window.addEventListener('unhandledrejection', this.onUnhandledRejection);
onUnhandledRejection = (event) => {
const exception = event.reason;
console.log(event)
if (process.env.NODE_ENV !== 'test') console.log('exception unhandled', exception);
if (exception instanceof HttpError) {
event.preventDefault();
this.setState({
errorMessages: this.generateHttpErrorMessages(exception)
});
return;
}
if (exception instanceof TypeError && exception.message === 'Failed to fetch') {
event.preventDefault();
this.setState({
errorMessages: {
user: 'Fetch failed',
admin: 'Problems with network or API, please contact IT-service'
}
});
return;
}
if (exception instanceof Error && exception.name === 'AbortError') {
event.preventDefault();
this.setState({
errorMessages: {
user: 'Request timeout fail.',
admin: `Request timeout fail, please contact IT-service`
}
});
return;
}
this.errorLoggGateway.loggError(exception.message);
};
Este es el método de renderización:
render() {
if (!this.state.hasLoaded) {
return ;
}
return (
<>
this.rebootApp()}/>
}/>
this.login(fnr)} />}
/>
{
({currentTime}) =>
}
}
/>
} />
);
}
Si echo un error del método en un componente infantil, en este caso ExamRootPage:
handleAnswer = (question, answer) => {
throw new Error('Crashed');
Tengo la pantalla de React usual con un error:
Error: Crashed
ExamRootPage.handleAnswer
C:/Users/myuser/Desktop/Projects/project/frontend/src/pages/ExamRootPage.js:193
190 | };
191 |
192 | handleAnswer = (question, answer) => {
> 193 | throw new Error('Crashed');
¿Por qué no? componentDidCatch
ni el onUnhandledRejection
¿No ha cogido ese error?
¿Cómo puedo arreglar esto para poder manejar esos errores allí?
Estoy usando la versión React ^16.12.0.
Pregunta hecha hace 3 años, 5 meses, 0 días - Por logicloom
2 Respuestas:
-
El problema que estás experimentando es que el método
componentDidCatch
y elonUnhandledRejection
no pueden capturar los errores lanzados por eventos síncronos como elthrow
en tu componenteExamRootPage
.Dado que
componentDidCatch
se enfoca en capturar errores específicamente de los componentes hijos durante el renderizado, yonUnhandledRejection
se enfoca en capturar promesas rechazadas no manejadas, ambos no son directamente capaces de interceptar errores lanzados de manera síncrona como en tu caso.Para manejar estos tipos de errores de manera más global, tienes algunas opciones:
- Utilizar un bloque try-catch en el método handleAnswer: La forma más sencilla de capturar errores lanzados de manera síncrona es envolver el código problemático con un bloque try-catch en el método `handleAnswer` de `ExamRootPage`.
Por ejemplo:
javascript handleAnswer = (question, answer) => { try { throw new Error('Crashed'); } catch (error) { // Manejar el error aquí // Por ejemplo, contar con el método componentDidCatch this.componentDidCatch(error, { componentStack: 'ExamRootPage.handleAnswer' }); } }
- Utilizar un gestor de errores de nivel superior: Puedes implementar un gestor de errores de nivel superior en tu aplicación que se encargue de capturar todos los errores no manejados. Este gestor de errores podría ser un componente de React que envuelve toda tu aplicación y captura cualquier excepción no controlada.
Por ejemplo:
javascript class ErrorBoundary extends React.Component { state = { hasError: false }; componentDidCatch(error, errorInfo) { this.setState({ hasError: true }); // Logear o manejar el error aquí } render() { if (this.state.hasError) { // Renderizar un componente de error personalizado return
; } return this.props.children; } } Donde utilizas este componente alrededor de tu aplicación principal:
javascript
Estas estrategias te permitirán capturar y manejar errores lanzados de manera síncrona como el caso que mencionas en tu componente
ExamRootPage
. ¡Espero que esto te ayude a resolver el problema!Respondida el Dec 18, 2020 a las 15:04 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
React 16 utiliza un modo de renderizado asincrónico, lo que significa que los errores lanzados durante el renderizado no siempre son capturados por
componentDidCatch
. Para manejar estos errores, puedes utilizar el método del ciclo de vidacomponentDidMount
para agregar un controlador de errores al ciclo de eventos de JavaScript:javascript componentDidMount() { window.addEventListener('error', this.handleError); } componentWillUnmount() { window.removeEventListener('error', this.handleError); } handleError = (event) => { // Registra el error en el servidor o realiza otras acciones de manejo de errores console.log(event.error); };
También puedes utilizar una librería como
react-error-boundary
para manejar errores de forma más declarativa:javascript import React, { ErrorBoundary } from 'react-error-boundary'; class MyErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { // Registra el error o muestra una interfaz de usuario de error console.log(error, errorInfo); } render() { if (this.state.hasError) { // Renderiza una interfaz de usuario de error return
Algo salió mal
; } return this.props.children; } } export default function MyComponent() { return ({/ Componentes hijos que pueden lanzar errores /} ); }Además, asegúrate de que estás manejando correctamente los errores en tu componente infantil
ExamRootPage
. Si estás lanzando errores en una función de devolución de llamada, es posible que debas utilizartry...catch
para capturar y manejar los errores dentro del componente.Respondida el Dec 18, 2020 a las 15:16 - por Gemini
Votos positivos: 0 | Votos negativos: 0