React Native: Ciclo de vida de Navegación

Una de las características más interesantes y clave de React y React Native son los métodos de ciclo de vida. Sobretodo sus métodos de ciclos de vida de los componentes. La API de React y la de React Native te permiten, mediante los métodos de ciclo de vida, saber qué eventos ocurren desde el “nacimiento” de un componente hasta su “muerte”.  

Estos métodos son particularmente útiles cuando lo que necesitas es “pescar” alguna funcionalidad, o establecer un valor nuevo a una variable, actualizando su “estado”, o state, siempre que pase algo en tu aplicación.

¿Cuál es el problema?

Si como yo, has empezado a usar React antes de React Native (RN), en RN tendrás la expectativa que si un usuario navega de una Ruta X a una Ruta Y, X se morirá - RN llamará componentWillUnmount() - y X se vuelve a montar después, cuando el usuario vuelva a la pantalla. ¡No necesariamente! Como bien sabes, la navegación en móvil tiene unas necesidades muy especiales y peculiares comparando con la Web.

Antes de seguir, lectura recomendada:

¿Cómo funciona?

En RN si tienes una pila de navegación con las pantallas X e Y, es cierto que cuando navegues a la pantalla X se llama su método componentDidMount(). Lo mismo pasa al navegar a la pantalla Y: RN llama a su método componentDidMount(). Lo que pasa es que el componente X sigue montado en la pila y no se llama componentWillUnmount(). Otro problema es que cuando vuelvas de X para Y, RN llama componentWillUnmount() de Y y no llama componentDiMount() de X, porque este ya está montado. ¿Aún estás conmigo? ;)

Entonces, ¿cómo saber dónde estoy?

Pues, este es el problema mayor y el motivo principal de este artículo. Si estás desarrollando tu primera aplicación en RN, y te has preguntado “¿Cómo puede mi aplicación saber si un usuario está saliendo o volviendo a una pantalla?”, este post es para tí.

Eventos de ciclo de vida de navegación de React Navigation

Gracias a la versión 3 de React Navigation, una biblioteca creada por la comunidad que te permite crear rutas y navegación de forma “más o menos” fácil, puedes tener acceso a eventos emitidos por React Navigation a Componentes Pantalla que hayan suscrito a estos eventos.  React Navigation es una caja de herramientas muy potente que vale la pena conocer a fondo.

¿Cuáles son los eventos disponibles?

De acuerdo con la documentación oficial, React Navigation  permite que te subscribas a 4 eventos diferentes: willFocus, willBlur, didFocus, didBlur. Aunque sus nombres a mi me parezcan bastante claros, su definición es la siguiente:

  • willFocus avisa que una pantalla se enfocará, que enfocarás una determinada pantalla.
  • willBlur dice si se desenfocará una pantalla.
  • didFocus informa que se ha enfocado una pantalla, por ejemplo si ha habido una transición y esta transición es completa.
  • didBlur notifica si se ha desenfocado una pantalla, o sea ha habido una transición y esta es completa.

¡Conociendo estos eventos ya sabes qué hacer si quieres llamar una función cuando una pantalla enfocada cambia!

¿Cómo suscribir?

Puedes usar addListener() para suscribir a actualizaciones a los ciclo de vida de navegación.

Por ejemplo:

Usamos componentDidMount para el Listener

Y eliminar el listener cuando ya hayas acabado:

Utilizamos componentWillUnmount para eliminar el listener

Si prefieres la versión declarativa, solamente tienes que “declarar” el componente NavigationEvents y utilizar sus props onWillFocus, onDidFocus, onWillBlur, onDidBlur.

Ejemplo:

NavigationEvents es una solución declarativa

Pero, ¿cómo sé realmente si está enfocada la pantalla?

Si has llegado hasta aquí, ¡premio! isFocused() es el método que necesitas utilizar para saber si una pantalla está enfocada o no. El método es muy práctico pues te retorna true o false según una cosa u otra. Aprovechando la propiedad navigation, lo puedes usar de la siguiente manera:

Declaramos isFocused con let y no const

Por cierto, ¿recuerdas la diferencia entre ‘let’ y ‘const’?

Esta forma de llamar isFocused es legítima y funciona correctamente, pero si quieres ir más allá, también puedes usar el método withNavigationFocus(). El método withNavigationFocus()  es un componente de alta orden que pasará una prop booleana isFocused a tu componente personalizado:

withNavigationFocus envolve tu Componente

withNavigationFocus retorna un componente que envolve MyScreen y le pasa la propiedad  de navegación. Como puedes ver en el ejemplo anterior, puedes acceder al estado si está la pantalla está enfocada o no en el método render() de tu componente pantalla, pero también podrías hacerlo en otro componente dentro de la pantalla. ¿Interesante?

State

Si has llegado hasta aquí, es porque tienes más interés en el tema y te estás preguntado, “cómo sé el nombre de la ruta?”. Pues,  una pantalla accede a su ruta mediante el objeto this.props.navigation.state. Este objeto contiene algo parecido a:

Tu lógica puede acceder a routeName

Con estos datos, puedes hacer lo que quieras, aplicando la lógica que deseas para realizar los cambios que quieres, como por ejemplo cambiar el color de alguna pantalla, o mostrar un mensaje según el usuario haya enfocado una, u otra vez determinada pantalla. Si tienes una mejor aplicación, ¿dejas un comentario? ;)

Conclusión

Ahora que ya conoces el ciclo de vida de (React) Navigation, ya puedes tenerlo en cuenta como una opción más para tus rutas y navegación siempre que desees innovar, y crear algo que no está contemplado inicialmente por el equipo de React Native. Cómo has podido ver,  estos eventos de ciclo de vida no sustituyen a los métodos de ciclo de vida de React, de hecho en algunos casos tendrás que usarlos juntamente, pero son una ayuda más para simplificar tu desarrollo de aplicaciones móviles con React Native.

¿Utilizas React Navigation en tus aplicaciones? Qué tal la experiencia?

Fotografía:  lumix2004 en Pixabay

Fuentes: