React

Agenda

  1. ¿Qué es React?
  2. Componentes
    1. JSX
    2. Componentes y props
    3. Estado y ciclo de vida
    4. Manejo de Eventos
    5. Renderizado Condicional

¿Qué es React?

Es una librería JavaScript de código abierto enfocada a la visualización.

Permite el desarrollo de interfaces de usuario de forma sencilla, mediante componentes interactivos y reutilizables.

Cuál es el objetivo de React?

Sirve para desarrollar aplicaciones web de manera más ordenada y con menos código que si se utiliza Javascript puro o librerías como jQuery centradas en la manipulación del DOM.

Ventajas de utilizar React
  • Fácil de aprender y simple de utilizar
  • Componentes reutilizables
  • Virtual DOM
  • Buenas herramientas de desarrollo
  • JSX
Fácil de aprender y simple de utilizar
  • Extensa documentación en su sitio oficial React
  • StackOverflow cuenta con una gran variedad de preguntas a problemas recurrentes y no tan recurrentes
  • Cualquiera que ya posea conocimientos de JS podrá comenzar a trabajar con React rápidamente
Componentes reutilizables
  • React está basado en Componentes, cada uno de estos encapsula su propia lógica y visualización
  • Cada componente puede ser reutilizado en cualquier parte del sitio que se desee
  • Evita la duplicación de código, alivianando la carga de desarrollo
Virtual DOM
  • React utiliza una representación "virtual" del DOM
  • Mejora el desempeño del sitio al realizar cambios sobre este DOM virtual
Buenas herramientas de desarrollo
  • Posee una extensa variedad de herramientas de desarrollo
  • Entre ellas se pueden mencionar, React Developers Tools, disponible para Chrome y Firefox
  • Si te encuentras utilizando Redux, existe un set similar de herramientas de desarrollo
JSX
  • Permite agregar elementos HTML sobre código JS
  • Ayuda a prevenir algunos tipos de ataques, por ejemplo XSS

JSX


              const elemento = 

Hola, mundo!

;

Esta sintaxis de etiquetas no es ni un string ni HTML. Se llama JSX, y es una extensión de la sintaxis de JavaScript. Si bien no es requerido su uso con React, se recomienda hacerlo para describir cómo debería ser la interfaz de usuario.


              const nombre = 'Juan Perez';
              const elemento = 

Hola, {nombre}

;

Se puede poner cualquier expresión JavaScript dentro de llaves en JSX. Por ejemplo, 2 + 2, usuario.nombre, o formatearNombre(usuario).

Puede usarse dentro de declaraciones if, loops, asignarlo a variables, aceptarlo como argumento, y retornarlo desde dentro de funciones:


              function obtenerSaludo(usuario) {
                if (usuario) {
                  return 

Hola, {formatearNombre(usuario)}!

; } return

Hola, Extraño.

; }

Se pueden usar comillas para especificar strings literales como atributos:


              
            

También se pueden usar llaves para insertar una expresión JavaScript en un atributo:


              
            

Aunque si la etiqueta no contiene hijos, se puede cerrar inmediatamente con />:


              
            

Dado que JSX es más cercano a JavaScript que a HTML, se usa la convención de nomenclatura camelCase (tabIndex) en vez de nombres de atributos HTML. A su vez, el atributo class se vuelve className en JSX, dado que class, como veremos, es palabra reservada.

Componentes y props

Los componentes permiten separar la interfaz de usuario en piezas independientes, reutilizables y pensar en cada pieza de forma aislada.

Conceptualmente, los componentes son como las funciones de JavaScript. Aceptan entradas (llamadas “props”) y devuelven elementos que describen lo que debe aparecer en la pantalla.

La forma más sencilla de definir un componente es escribir una función de JavaScript:


              function Bienvenida(props) {
                return 

Hola, {props.nombre}

; }

Esta función es un componente de React válido porque acepta un solo argumento “props” con datos y devuelve un elemento de React. Llamamos a dichos componentes “funcionales” porque literalmente son funciones JavaScript.

También se puede utilizar una clase para definir un componente:


              class Bienvenida extends React.Component {
                render() {
                  return 

Hola, {this.props.nombre}

; } }

Los dos componentes anteriores son equivalentes desde el punto de vista de React.

Como se puede ver, para acceder a las props de un componente clase, es necesario usar this.props. El this refiere a un elemento JavaScript, dependiendo del contexto en el que se encuentra. En este caso de componentes clase, refiere a la clase (o a un objeto de esa clase).

Anteriormente, sólo encontramos elementos de React que representan las etiquetas del DOM:


              
            

Los elementos también pueden representar componentes definidos por el usuario:


              
            

Cuando React ve un elemento representando un componente definido por el usuario, pasa atributos JSX e hijos a este componente como un solo objeto. Llamamos a este objeto “props”. Por ejemplo, para el componente Bienvenida definido anteriormente, este código muestra “Hola, Sara” en la página:


              
            

Como se vio, los componentes pueden referirse a otros en su salida. Así, podemos crear un componente App que renderiza Bienvenida muchas veces:


              
            

Cada vez que cambie una prop del componente, el método render se invocará, actualizando la interfaz. Pero un componente no puede modificar sus propias props. Que cambien significa que el componente padre le pase otros valores como props.

Ya sea que declares un componente como una función o como una clase, las props son de solo lectura. No ocurre lo mismo con el estado (state) de un componente, como veremos a continuación.

Estado y ciclo de vida

El estado es similar a las props, pero es privado y está completamente controlado por el componente.

Vamos a implementar un componente Reloj que se actualice cada un segundo para mostrar la hora.

Para usar estado, se debe especificar el constructor de la clase y definir el estado en el mismo, de la forma:


              class Reloj extends React.Component {
                constructor(props) {
                  super(props);
                  this.state = {fecha: new Date()};
                }
              
                render() {
                  return (
                    

Hola, mundo!

); } }

Hemos definido el estado pero no lo hemos usado aún. Vamos a mostrar en pantalla el estado:


              class Reloj extends React.Component {
                constructor(props) {
                  super(props);
                  this.state = {fecha: new Date()};
                }
              
                render() {
                  return (
                    

Hola, mundo!

Son las {this.state.fecha.toLocaleTimeString()}.

); } }

Como se pudo ver, se hace de la misma forma que para las props, pero usando state.

Queremos configurar un temporizador cada vez que Reloj se renderice en el DOM por primera vez. Esto se llama «montaje» en React. También queremos borrar ese temporizador cada vez que el DOM producido por Reloj se elimine. Esto se llama «desmontaje» en React. Podemos declarar métodos especiales en la clase del componente para ejecutar algún código cuando un componente se monta y desmonta:


              class Reloj extends React.Component {
                constructor(props) {
                  super(props);
                  this.state = {fecha: new Date()};
                }

                componentDidMount() {
                }
              
                componentWillUnmount() {
                }
              
                render() {
                  return (
                    

Hola, mundo!

Son las {this.state.fecha.toLocaleTimeString()}.

); } }

Estos métodos son llamados «métodos de ciclo de vida» del componente (lifecycle methods).

El método componentDidMount() se ejecuta después que la salida del componente ha sido renderizada en el DOM. Este es un buen lugar para configurar un temporizador:


              componentDidMount() {
                this.idTemporizador = setInterval(
                  () => this.tick(),
                  1000
                );
              }
            

Notar cómo guardamos el ID del temporizador en this (this.idTemporizador). Si bien this.props es configurado por el mismo React y this.state tiene un significado especial, se puede añadir campos adicionales a la clase manualmente si se necesita almacenar algo que no participa en el flujo de datos (como el ID de un temporizador).

Eliminaremos el temporizador en el método de ciclo de vida componentWillUnmount():


              componentWillUnmount() {
                clearInterval(this.idTemporizador);
              }
            

Finalmente, implementaremos el método tick() que Reloj ejecutará cada segundo. Utilizará this.setState() para actualizar el estado del componente.


              
            

De esta forma, al cambiar el estado, el componente se actualiza y se invoca el método render, provocando que se actualice la interfaz.

Si bien el estado es local al componente y solo éste puede leerlo o modificarlo, un componente puede pasar como prop el valor de su estado a un componente hijo. El componente hijo no tiene forma de saber que ese valor viene del estado del componente padre. Simplemente, lo usa como prop (solo lectura).

A esto comúnmente se le llama flujo de datos «descendente» o «unidireccional». Cualquier estado siempre es propiedad de algún componente específico, y cualquier dato o interfaz de usuario derivados de ese estado solo pueden afectar a los componentes «debajo» de ellos en el árbol.

Manejo de Eventos

Los eventos son acciones que ocurren y provocan algún cambio o notificación en el Sistema.

Cuando programamos nuestra página, nosotros decidimos sobre qué eventos queremos reaccionar y cómo.

Tipos de Eventos

Existen muchos tipos de eventos distintos, por ejemplo:

  • Hacer click sobre algún elemento
  • Presionar alguna tecla
  • Pasar el mouse por arriba de algún elemento (hover)
  • Cambiar algún campo de un formulario (change)
  • Apretar el botón de confirmar de un formulario (submit)

Detectar Eventos en React

Para detectar el evento click se puede utilizar la propiedad onClick de los elementos:

manejadorClick es una función definida dentro de la clase. Para que funcione, es necesario hacer un bind en el constructor:


              this.manejadorClick = this.manejadorClick.bind(this);
            

Una forma de evitar hacer el bind, es utilizar Funciones Flecha:

Este código es equivalente al anterior, ahorrando la necesidad de hacer el bind en el constructor.

Por esto, de ahora en adelante, usaremos funciones flecha.

Pasar parámetros a los manejadores

Muchas veces vamos a precisar mandar parámetros extra a la función que maneja el evento, por ejemplo, un identificador.

La función eliminarFila va a recibir 2 parámetros:

  1. id: identificador de la fila
  2. e: el evento ocurrido

Renderizado Condicional

En React, se pueden crear distintos componentes que encapsulen el comportamiento que se quiere.

Se puede renderizar algunos de ellos, dependiendo del estado de la aplicación.

Esto hace que no siempre se vea lo mismo, sino que dependiendo del estado de la aplicación se va a ver un componente u otro.

Para hacer esto, se puede usar el operador if

Supongamos que tenemos estos dos componentes:

y queremos que se vea uno u otro dependiendo si el usuario está registrado o es un invitado.

Vamos a crear un un componente Bienvenida que mueste el mensaje adecuado:

Una alternativa al operador if es utilizar el Operador Condicional Ternario que brinda javascript:

Este código es equivalente al recién visto, donde:

condición ? verdadero : falso

Variables de Elementos

Se pueden usar variables para almacenar elementos.

Sirve para renderizar condicionalmente una parte del componente mientras el resto del resultado no cambia.

Supongamos que tenemos dos botones, para iniciar y cerrar sesión respectivamente:

Vamos a crear un componente con estado, llamado ControlSesion.

El componente va a renderizar BotonIniciarSesion o BotonCerrarSesion dependiendo de su estado actual. También va a renderizar Bienvenida del ejemplo anterior.

Notar que usamos las funciones flecha para evitar el bind y en lugar del if usamos el Operador Ternario.

Declarar una variable y usar if es una buena forma de renderizar condicionalmente un componente pero también hay formas de hacer condiciones en una sola línea en JSX.

Para incluir expresiones en JSX hay que envolver el código con las llaves "{ }". Para incluir condicionalmente un elemento puede ser útil usar el operador lógico && de JavaScript.

En este caso, solo se muestra la cantidad de mensajes sin leer si se tiene al menos 1 mensaje sin leer.

Esto funciona porque en JavaScript:

  • true && expresión = expresión
  • false && expresión = false

Por eso, si la condición es true, el elemento justo después de && aparecerá en el resultado. Si es false, React lo ignorará.