ReactJS: Ciclo de vida de un componente

Después de haber comenzado con ReactJS: Instalar todo lo necesario para empezar e Introducción a ReactJS, vamos a ir un poco más profundo en cómo funcionan los componentes de React.

Cuando creamos un componente e interactuamos con el pasa por un ciclo de vida. Si conocemos que pasa en cada paso podemos aprovechar de hacer modificaciones o reaccionar a ciertos eventos para hacer nuestro componente y aplicación comportarse como queremos.

Vamos a ver 3 ciclos:

  1. Inicialización del componente
  2. Actualización del componente
  3. Destrucción del componente

Y veremos en cada ciclo que métodos son llamados y que propiedades están disponibles.

1. Inicialización del Componente

Esta es la fase inicial donde el componente es creado.

Los métodos y triggers que son llamados durante esta fase son:

  1. getInitialState
  2. getDefaultProps
  3. componentWillMount
  4. render
  5. componentDidMount

getInitialState

Este es llamado sólo una vez antes de que el componente se monte. Regresará el valor inicial de this.state.

getDefaultProps

Solo se invoca una sola vez y es guardado en cache cuando el componente es creado. Los valores serán guardados en this.props.

Como es invocado antes de la creación de cualquier instancia no puede depender en los valores anteriores de this.props.

componentWillMount

Invocado solo una vez justo antes que se llame al render del componente, tanto en el cliente como en servidor, si se coloca un valor de estado (this.state) dentro de este método no provocará una actualización.

render

Este método retorna el componente como tal para su visualización, sino quieres que se muestra nada debes retornar null o false. Es el único método requerido siempre por los componentes.

Esta función debe ser pura, lo que quiere decir que no debe modificar el estado del componente y que regresará el mismo resultado cada vez que se llame. Tampoco debe leer o escribir directamente al DOM o interactuar con el navegador, para este tipo de intereacciones se pueden utilizar otros métodos como por ejemplo componentDidMount().

componentDidMount

También se invoca una sola vez, sólo en el cliente, y es llamado inmediatamente después de la vizualización inicial (realizada por la función render). En este método ya puedes acceder a cualquier referencia de los componentes hijos, el método componentDidMount de los hijos es siempre llamado antes que el de los padres.

En este método puedes integrar otros frameworks de Javascript, colocar timers con setTimeOut o setInterval o hacer llamadas AJAX.

Aquí finaliza la fase de inicialización y el componente debería ya mostrarse en nuestro navegador.

2. Actualización

La fase de actualización pasa o cuando hay nuevos props o cuando cambia el estado.

  1. componentWillRecieveProps (solo cuando hay nuevos props)
  2. shouldComponentUpdate
  3. componentWillUpdate
  4. render
  5. componentDidUpdate

componentWillRecieveProps

Sólo es llamado cuando un componente está recibiendo nuevos props. Podemos utilizar este método para actualizar el estado (this.state) sabiendo que va a haber un cambio en los props.

Los valores antiguos de los props se pueden acceder con this.props ya que aún no se han actualizado.

Este método recibe como parámetros los valores de los props a actualizar.

Por ejemplo:

componentWillReceiveProps: function(nuevosProps) {
  this.setState({
    votos: nuevosProps.votos > this.props.votos
 });

Nota importante: NO implica que un cambio de estado vaya a generar un cambio en los props.

Este método NO es llamado cuando hay un cambio de estado.

shouldComponentUpdate

Es llamado antes de render cuando son recibidos nuevos props o estados. Este método por defecto retorna true, pero si estamos seguro que la actualización de los props o el estado no requiere que se actualice el componente puedes sobreescrbirlo y retornar false, en cuyo caso no se llamara a método render hasta el próximo cambio y tampoco se llamarán a los métodos componentWillUpdate y componentDidUpdate.

Aquí es donde es importante la inmutabilidad del estado del componente, en este método podemos hacer comparaciones entre los cambios y ver si es necesario actualizar o no. Esto nos permite obtener mejor rendimiento y menos uso de nuestros recursos.

Por ejemplo podemos verificar si no hubo cambios en nuestro props y si es así no actualizar.

shouldComponentUpdate: function(nuevosProps, nuevoEstado) {
  return nuevosProps.id !== this.props.id;
}

También como se muestra tenemos acceso al nuevoEstado, por lo que podemos hacer otras comparaciones y ver si es necesario actualizar o no.

Este método no se llama en la inicialización.

componentWillUpdate

Se llama justo antes de llamar a render(), cuando se reciben los nuevos props o estados. Aquí podemos hacer preparaciones antes de que ocurra la actualización.

Es importante saber que NO podemos utilizar this.setState() en este método, si necesitamos cambiar el estado debido a un cambio en los props debemos usar el método componentWillReceiveProps que vimos anteriormente.

Ejemplo:

componentWillUpdate: function(nuevosProps, nuevoEstado) {
  ...
}

Este método no se llama en la inicialización.

render

Es igual al que vimos en la fase de inicialización y es donde se crea el componente como tal.

componentDidUpdate

Se llama justo después de render después que todos los cambios han sido hechos en el DOM. Puedes utilizar este componente para hacer alguna operación el DOM después que el componente se haya actualizado.

componentDidUpdate: function(anteriorProps, anteriorEstado) {
  ...
}

3. Destrucción

Esta es la última fase y es cuando el componente se destruye y consiste en un sólo método.

componentWillUnmount

Es llamado justo antes de que el componente sea removido del DOM, es útil para hacer cualquier operación de limpieza, tales como invalidar timers, eliminar elementos que se hayan creados durante componentDidMount y cualquier otra operación pendiente.

Conclusión

Siempre es importante conocer por cuales ciclos de vida pasa cualquier elemento de nuestra aplicación, muchas veces tratamos de realizar operaciones donde no corresponde, o queremos evitar que pasen ciertos eventos cuando se cumplen ciertos valores, o queremos acceder a datos antes de que se muestren y todo lo podemos hacer con los métodos que vimos.

También te pueden interesar ReactJS: Instalar todo lo necesario para empezar e Introducción a ReactJS.

Como siempre si tienen cualquier duda o sugerencia siempre son bienvenidos los comentarios.