Condicionales en React

El renderizado condicional es una pieza clave de cualquier lenguaje de templado. React no tiene ninguna sintaxis propia para manejar este tipo de situaciones. Debemos usar los operadores booleanos de Javascript.

En este artículo veremos algunos consejos y buenas prácticas para escribir condicionales en JSX . 

Renderizando un 0: 

Renderizar en base a una condición numérica es un caso bastante común, por ejemplo renderizar una lista o en caso de que la lista esté vacía, renderizar un mensaje indicando que no hay elementos a mostrar.

Uno podría pensar que el siguiente código es válido: 

{miLista.length && <ListaElementos lista={miLista}>}

Sin embargo, si la lista está vacía, se va a mostrar un 0 en nuestro DOM. Esto es por como funciona && en Javascript. Un ‘falsy’ del lado izquierdo (el cero en este caso) es retornado de manera inmediata. En Javascript los operadores booleanos no castean su resultado a booleano. Por esto React mostrará un 0 en el DOM

¿Quere saber más sobre truthy y falsy? Te recomiendo este post

La solución a esto es usar o castear un booleano. Por ejemplo: 

{miLista.length > 0 && <Componente />}
{!!miLista.length && <Componente />}
{Boolean(miLista.length) && <Componente />}

Ternarios con responsabilidad

Los ternarios son una solución sencilla a la hora de renderizar condicionalmente. El problema es que no escalan bien. A partir del segundo ternario el código empieza a ser bastante desprolijo y complicado de entender. 

Tomemos como ejemplo el siguiente fragmento.

{tieneDescuento
? <OfertaDescuento />
: tieneCupon
     ? <OfertaCupon />
     : <SinOferta />}

Esto se puede expresar de una manera mucho más simple y fácil de entender: 

{tieneDescuento && <OfertaDescuento />}
{tieneCupon && <OfertaCupon />}
{!tieneDescuento && !tieneCupon && <SinOferta />}

Otra opción es simplemente poner toda esta lógica en una función fuera del return/render().

const obtenerOferta = () => {
    if (tieneDescuento) return <OfertaDescuento />;
    if (tieneCupon) return <OfertaCupon />;
    return <SinOferta />;
};

Aplicando Lógica: 

En la algebra booleana && (and/y) tiene mayor precedencia que || (or/o). Este detalle es algo que se debe tener en cuenta a la hora de renderizar condicionalmente en React. 

Tomemos el siguiente ejemplo: 

usuario.anonimo || usuario.restringido && <div className=”error” />

Este código es equivalente a 

usuario.anonimo || (usuario.restringido && <div className=”error” />)

Para usuarios anónimos termina siendo (true || … el resto …) porque javascript sabe que la condición OR será “true” tan solo mirando el lado izquierdo y simplemente ignora el resto. React no renderiza “true” y aunque lo hiciera no se mostraría el <div> que especificamos. 

Como una buena práctica, se puede poner paréntesis a las condiciones OR || para estar seguro de lo que queremos que ocurra.

(Usuario.anonimo || usuario.restringido) && <div className=”error” />

Condicionales con JSX

Los elementos pasados vía props no se deben utilizar como condicionales. Tomemos el siguiente ejemplo 

const Wrap = (props) => {
    if (!props.children) return null;
    return <div>{props.children}</div>
};

Si children está vacío uno esperaría que retorne null. Pero props.children podría ser un array vacío, lo que devuelve true. 

Props.children.length también falla, children podría ser un solo elemento y no un array.

React.Children.count(props.children) soluciona el problema, ya que soporta tanto múltiples elementos como uno solo. El problema es que si paso algo como {false && “hola”}{false && “mundo”}, ese método nos dice que tenemos 2 elementos. Cuando en realidad no tenemos ninguno, ya que ese código no renderiza nada. 

Una posible solución a este problema yace en los estilos CSS con la pseudo-clase “:empty” 

Por todo esto no se recomienda usar las props como condicionales. En caso de hacerlo se debe pensar bien que recibirá el componente como props y plantear una la condición en base a eso.

¿Volver a montar o actualizar?

Consideremos el siguiente código: 

{condicion ? <Item id={1} /> : <Item id={2} />}

¿Qué sucede si la condición cambia? Uno podría pensar que <Item id={1} /> se desmonta y luego se monta <Item id={2} />. Spoiler no pasa eso. 

React simplemente actualiza las props del componente que ya esté montado, es decir el código de arriba es equivalente a: 

<Item id={condicion ? 1 : 2} />

Si el primer ejemplo tuviese dos componentes diferentes ({condicion ? <Item1 /> : <Item2 />}), React monta el otro componente ya que Item1 no puede ser actualizado a Item2

Esto puede causar comportamientos inesperados dependiendo de cómo se manejan las actualizaciones del componente, si se las maneja de manera adecuada es inclusive un poco mas optimo que remontar. 

Sin embargo, con los inputs esto puede causar algunos problemas. 

{modo === ‘nombre’
    ? <input placeholder="nombre" />
    : <input placeholder="telefono" />}

En este ejemplo si pongo algo en el input nombre y luego cambio al modo telefono, los datos que puse en nombre se ‘filtraran’ en el input de teléfono. Esto puede causar problemas más graves en sistemas mas complejos. 

No queda claro? Probalo en este sandbox

Una posible solución es la prop ‘key’. Normalmente la usamos a la hora de renderizar listas, pero key es una prop que le permite a React identificar un componente. 

// remonta al cambiar 
{modo === 'nombre'
    ? <input placeholder="nombre" key="nombre" />
    : <input placeholder="telefono" key="telefono" />}

El resumen: 

Resumiendo aca van mis tips para usar condicionales 

  • {number && <JSX />} renderiza un 0. Usar {number > 0 && <JSX />} 

  •  No olvidar usar parentesis en las condiciones or (||)  {(cond1 || cond2) && <JSX />}

  • Los Ternarios no escalan, usar bloques && ({condicion && <Valor />}) o poner la logica en una función por afuera del render. 

  •  No se puede saber al 100% si props.children contiene algún elemento - CSS empty es el mejor aliado en estos casos. 

  • {condicion ? <JSX props1 /> : <JSX props2 />} no va a desmontar el componente. Usar una key para lograr ese comportamiento.  

 

Siguiendo estos consejos te vas a ahorrar comportamientos raros y horas debugeando una simple condición.

 

 

Mandanos tus sugerencias

Ayudanos con ideas para los artículos de este blog a contacto@somospnt.com

¡Seguínos en nuestras redes sociales para enterarte de los últimos posts!