¿Cuál es la diferencia entre getDerivedStateFromError y componentDidCatch?

8 minutos de lectura

Avatar de usuario de Tomasz Mularczyk
Tomasz Mularczyk

Lo que entendí de aquí:

componentDidCatch:

  • se llama siempre en el navegador
  • se llama durante la “fase de compromiso” cuando el DOM ya se ha actualizado
  • debe usarse para algo como el informe de errores

getDerivedStateFromError:

  • también se llama durante la representación del lado del servidor
  • se llama en “fase de renderizado” cuando el DOM aún no se ha actualizado
  • debe usarse para representar una interfaz de usuario alternativa

Aún así, estoy un poco confundido acerca de algunas cosas:

  1. ¿Ambos detectan el mismo tipo de errores? o cada ciclo de vida detectará el error diferente?
  2. ¿Debería usar siempre ambos (posiblemente en el mismo componente de “captura de errores”)?
  3. “El uso de componentDidCatch para la recuperación de errores no es óptimo porque obliga a la interfaz de usuario alternativa a renderizarse siempre de forma síncrona” ¿qué está mal con eso?

Avatar de usuario de Estus Flask
Frasco de estus

Las declaraciones en la pregunta son en su mayoría correctas. Actualmente, los límites de error no se admiten en SSR, getDerivedStateFromError y componentDidCatch no afecta el lado del servidor.

¿Ambos detectan el mismo tipo de errores? o cada ciclo de vida detectará el error diferente?

Están detectando los mismos errores pero en diferentes fases. Esto antes era posible con componentDidCatch solo:

  static getDerivedStateFromError() {
    return { hasError: true };
  }

y

  componentDidCatch() {
    this.setState({ hasError: true });
  }

hacer la misma cosa, componentDidCatch no tiene posibilidades de ser compatible en el lado del servidor hasta que se agregue el soporte para la representación asíncrona ReactDOMServer.

¿Debería usar siempre ambos (posiblemente en el mismo componente de “captura de errores”)?

pueden Usa ambos. Un ejemplo de la documentación muestra que:

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    logComponentStackToMyService(info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children; 
  }
}

En este caso, las responsabilidades se dividen entre ellos. getDerivedStateFromError hace lo único para lo que es bueno, es decir, actualiza el estado si ocurre un error, mientras que componentDidCatch proporciona efectos secundarios y puede acceder this instancia de componente si es necesario.

“usar el componenteDidCatch para la recuperación de errores no es óptimo porque obliga a la interfaz de usuario alternativa a renderizarse siempre de forma sincrónica” ¿qué tiene de malo?

Los nuevos lanzamientos de React están destinados a la representación asíncrona, que es más eficiente. Como también se mencionó en el comentariola representación síncrona no es una gran preocupación para la interfaz de usuario alternativa porque puede considerarse un caso extremo.

  • ¡Agradable! ¿Podría también explicarme el tercer punto que acaba de agregar a la pregunta?

    – Tomasz Mularczyk

    24 de octubre de 2018 a las 7:32

  • Por supuesto. Actualicé la respuesta.

    – Frasco de estus

    24 de octubre de 2018 a las 7:35

  • Una parte de la información en OP es incorrecta (al igual que la información en el hilo de Reddit al que se vincula). getDerivedStateFromError NO se llama durante la representación del lado del servidor. He probado esto tanto en React 16.4 como en 16.7. Reaccionar documentos reactjs.org/docs/error-boundaries.html estado “Los límites de error no detectan errores para… Representación del lado del servidor”

    – Overlook Motel

    6 de enero de 2019 a las 11:10

  • npmjs.com/package/react-ssr-error-límite es una solución alternativa que hace que los límites de error funcionen en el servidor, que se puede usar hasta que aparezca el nuevo renderizador asíncrono React más adelante este año.

    – Overlook Motel

    7 de enero de 2019 a las 12:11

  • ¿Eso significa que si quiero mostrar un mensaje de brindis sobre la interfaz de usuario existente, diga “sin conexión de red”, podría usar componentDidCatch?

    – Jonathan

    11 de enero de 2021 a las 12:57

Avatar de usuario de Shubham Khatri
Shubham Khatri

Ambos métodos se llaman cuando hay un error durante la representación, en un método de ciclo de vida o en el constructor de cualquier componente secundario. Se pueden usar al implementar límites de error

De acuerdo con la Reaccionar documentos

getDerivedStateFromError El ciclo de vida se invoca después de que un componente descendiente haya generado un error. Recibe el error que se lanzó como parámetro y debe devolver un valor para actualizar el estado.


¿Ambos detectan el mismo tipo de errores? o cada ciclo de vida detectará el error diferente?

Ambos métodos de ciclo de vida detectarán los mismos errores, pero los argumentos de ambos componentes son diferentes.

Tiempo getDerivedStateFromError recibe solo el error como argumentos, componenteDidCatch también recibe el segundo parámetro que es info, i.e An object with a componentStack key containing information about which component threw the error.

getDerivedStateFromError() se llama durante la fase de “renderización”, por lo que no se permiten efectos secundarios. Para esos casos de uso, utilice componentDidCatch() en cambio. Tiempo componentDidCatch también se puede usar para establecer el estado, pero quedará obsoleto en versiones futuras

componentDidCatch debe usarse para efectos secundarios como errores de registro


También @Brian Vaughn ha elaborado más sobre su uso en el enlace que proporciona

getDerivedStateFromError funciona con renderizado del lado del servidor.
componenteDidCatch es un ciclo de vida de fase de confirmación, pero no hay fase de confirmación en el servidor. getDerivedStateFromError es un ciclo de vida de fase de procesamiento y, por lo tanto, se puede usar para habilitar el manejo de errores en el servidor.

La recuperación de la fase de renderizado es más segura. La historia de la recuperación de errores a través de
componentDidCatch es un poco inestable, ya que se basa en una confirmación intermedia de “nulo” para todo lo que está debajo del componente que produjo el error. Esto podría dar lugar a errores posteriores dentro de cualquier componente superior en el árbol que implemente componentDidMount o componentDidUpdate y simplemente suponga que sus referencias no serán nulas (porque siempre están en el caso de no error).

getDerivedStateFromError no fuerza la representación sincronizada. Debido a que las actualizaciones de estado de los ciclos de vida de la fase de confirmación siempre son sincrónicas, y debido a que se llama a componentDidCatch durante la fase de confirmación, el uso de componentDidCatch para la recuperación de errores no es óptimo porque obliga a la interfaz de usuario alternativa a renderizarse siempre de forma sincrónica. (Es cierto que esto no es una gran preocupación, ya que la recuperación de errores debería ser un caso extremo).

En el caso de un error, su límite de error
getDerivedStateFromError() primero se llamará al método (para actualizar el estado), luego al método render() (para realmente representar la interfaz de usuario alternativa), y luego componentDidCatch (una vez que la interfaz de usuario alternativa se haya comprometido con el DOM).

Si su límite de error define otros métodos de ciclo de vida (p. ej., componentWillUpdate, componentDidUpdate), también se les llamará, como lo harían en cualquier otro procesamiento.


“usar el componenteDidCatch para la recuperación de errores no es óptimo porque obliga a la interfaz de usuario alternativa a renderizarse siempre de forma sincrónica” ¿qué tiene de malo?

lo que significa es que se llama al componenteDidCatch después del método de representación que representa la interfaz de usuario alternativa y eso podría generar más problemas mientras getDerivedStateFromError actualiza el estado antes de la fase de procesamiento para que se procese la interfaz de usuario alternativa correcta y no se produzcan más errores en los componentes procesados. Además, los nuevos lanzamientos apuntan a la representación asíncrona, lo que podría tener problemas con el enfoque actual.

  • “El uso de componentDidCatch para la recuperación de errores no es óptimo porque obliga a la interfaz de usuario alternativa a renderizarse siempre de forma sincrónica”. No entiendo completamente lo que significa que se “renderizará sincrónicamente”. Quiero decir, ¿qué hay de malo en eso?

    – Tomasz Mularczyk

    24 de octubre de 2018 a las 7:26


  • @TomaszMularczyk, lo que significa es que se llama al componenteDidCatch después del método de representación que representa la interfaz de usuario alternativa y eso podría generar más problemas mientras getDerivedStateFromError actualiza el estado antes de la fase de representación para que se represente la interfaz de usuario alternativa correcta y no se produzcan más errores. los componentes renderizados. Además, los nuevos lanzamientos apuntan a la representación asíncrona, lo que podría tener problemas con el enfoque actual.

    – Shubham Jatri

    24 de octubre de 2018 a las 7:36


Avatar de usuario de AmerllicA
AmerllicA

En realidad, ambos tienen el mismo objetivo pero en una fase diferente, definitivamente, para escribir. ErrorBoundary componente que uso el getDerivedStateFromError método porque obedezco el Documentos de ReactJs. el doc tiene esta oración:

Usar estático getDerivedStateFromError() para representar una interfaz de usuario alternativa después de que se haya producido un error. Usar componentDidCatch() para registrar la información del error.

Seguramente, tiene algunas razones, por lo que para renderizar la interfaz de usuario alternativa siempre uso getDerivedStateFromError y para capturar información y hacer algo que uso componentDidCatch.

  • codepen.io/gaearon/pen/wqvxGa Entonces, ¿este ejemplo es un poco incorrecto, ya que establece el estado en componentDidCatch en lugar de ponerlo en getDerivedStateFromError ? Gracias

    – tonix

    29 de mayo de 2020 a las 8:51


¿Ha sido útil esta solución?