22

5 Antipatrones en React que deberías evitar (y sus alternativas)

49166Puntos

hace 2 años

Los antipatrones son ejemplos bien documentados de malas soluciones para problemas comunes. En esta lectura te voy a contar acerca de malas practicas que se pueden presentar en el ecosistema de React.

1. Usar el index como key cuando iteras una lista

En la mayoría de tus proyectos frontend debes consumir una API para alimentar tus vistas. Dichas API’s suelen devolver un array con todos los datos necesarios para nuestros componentes. Un claro ejemplo de esto son los e-commerce con una infinidad de artículos que podemos apreciar en cards con diferente información.

Pero React necesita saber con exactitud qué elemento está renderizando, por lo que siempre nos pide una key cuando ocupamos métodos como map para saber lo que está pasando con el estado de cada componente.

El problema de usar el index como key, ese que nos proveen los métodos nativos, es que puede cambiar si agregamos o quitamos elementos, ya que los indices se actualizarán y React no sabrá identificar los nuevos valores.

En su lugar te recomiendo siempre usar el id que venga desde la API o librerías que te permitan crear ID’s dinámicos

// Usando el id proveniente de tu API✅
{
  items.map((item) =><Product {...item} key={item.id} />)
}

// Usando un id generado (en caso que tu API no contenga ID's)✅
{
  items.map((item) =><Product {...item} key={newId} />)
}

// Usando el id de map ❌
{
  items.map((item, id) =><Product {...item} key={id} />)
}

💡 Las keys siempre deben llegar como strings, así que asegúrate de hacer el cambio si es necesario.
Dominando las Keys en React.js

2. Hacer que useEffect sea una función asíncrona directamente

Esto suena extraño porque por lo regular hacemos llamadas a API’s dentro de este hook. Pero podemos cometer un error muy grave a la hora de implementar async await.

En vez de enviar una función asíncrona directamente como primer argumento para tu efecto, puedes enviar una función normal y dentro de esta crear o llamar a la función ahora sí asíncrona.

// ❌ Lo que no debes hacerimport React, { useState, useEffect } from "react";

const MyBadComponent = () => {
  const [data, setData] = useState(null);
  const API = "https://...";

  useEffect(async () => {
    // Si la función anónima que recibe este hook la// pasamos de esta forma, React fallará debido a que// se le será imposible ejecutar el cleanup aunque no lo// necesitemos
    let response = await API;
    response = await response.json();
    setData(response);
  });
};

// ✅ Lo que si debes hacer con async/awaitconst MyGoodComponent = () => {
  const [data, setData] = useState(null);
  const API = "https://...";

  useEffect(() => {
    // En cambio, useEffect admite sin problemas una// función asíncrona de la siguiente formaconst fetchData = async () => {
      let response = await API;
      response = await response.json();
      setData(response);
    };

    fetchData();
  });
};

// ✅ Otra manera de consumir API'simport React, { useState, useEffect } from "react";

const AnotherGoodComponent = () => {
  const [data, setData] = useState(null);
  const API = "https://...";

  useEffect(() => {
    // Si te quieres evitar tanto problema, puedes implementar// la llamada con Promise.then()
    fetch(API)
      .then((response) => response.json())
      .then((json) => setData(json));
  });
};

3. Manejar un solo hook de estado para tu componente

Desde que llegaron los hooks a React el manejo del estado se volvió más sencillo, así que no te tienes que preocupar por tener un solo estado que englobe toda la data de tus vistas, en su lugar puedes tener varios con un fin en específico.

Pero ojo, el hacer uso excesivo de los estados también puede llegar a considerarse una mala practica. Entonces… ¿cuál es el punto medio?

Imagina que tienes un estado que recopila la información de tus usuarios, como el nombre, apellido, edad y email. Te voy a presentar dos formas en las que lo podrías hacer:

// Usar un estado por cada campo ❌
import React, { useState } from "react";

const UserInformation = () => {
  const [name, setName] = useState("");
  const [lastName, setLastName] = useState("");
  const [age, setAge] = useState();
  const [mail, setMail] = useState("");

  // Y si agregamos otro tipo de estado para verificar la carga de nuestros// tendríamos más lineas de este estiloconst [isLoading, setLoading] = useState(true);
  const [error, setError] = useState("");

  return (
    <form>
      <inputtype="text"
        name="name"
        onChange={(e) => setName(e.target.value)}
      />
      <inputtype="text"
        name="lastName"
        onChange={(e) => setLastName(e.target.value)}
      />
      <inputtype="number"
        name="age"
        onChange={(e) => setAge(e.target.value)}
      />
      <inputtype="email"
        name="email"
        onChange={(e) => setMail(e.target.value)}
      />
      <button type="submit">
        Submit
      </button>
    </form>
  );
};

const CleanUserInformation = () => {
  const [userData, setUserData] = useState({});
  const [isLoading, setLoading] = useState(true);
  const [error, setError] = useState("");

  // Solo debes crear una función como la siguiente para que modifique el estado// con los datos de tu usuarioconst handleSubmit = (event) => {
    setUserData({
      name: e.target.name.value,
      lastName: e.target.lastName.value,
      age: e.target.age.value,
      mail: e.target.email.value,
    });
  };

  return (
    <form onSubmit={handleSubmit}>
			<inputtype="text" name="name" />
			<inputtype="text" name="lastName" />
			<inputtype="number" name="age" />
			<inputtype="email" name="email" />
			<button type="submit">
				Submit
			</button>
		</form>
	);
};

Evita el exceso. 🥤

4. Anidar componentes

Esta practica no se consideraría mala, realmente tiene algo de sentido el crear un componente dentro de otro debido a que solo se usará una única vez y sirve para que el render del componente padre se vea más limpio. Sin embargo, el hacer esto puede hacer que React tenga problemas de rendimiento.

Trata de evitarlo siempre que puedas.

// ❌
const ParentComponent = () => {
  let [name, setName] = useState("Platzinauta");

  const ChildComponent = () => {
    return <h1>Hello {name}</h1>;
  };return (
    <div><ChildComponent /></div>);
};// ✅// El componente hijo se queda por fuera del componente padre
const ChildComponent = ({ name }) => {
  return <h1>Hello {name}</h1>;
};

export const ParentComponent = () => {
  let [name, setName] = useState("Platzinauta");return (
    <div><ChildComponent name={name} /></div>
  );
};

5. No aplicar el principio de DRY (Don’t repeat yourself)

Esto es un tema muy amplio que necesita una lectura entera para hablar de él, pero voy a simplificarlo para que te des una idea de como empezar a implementar esta buena practica en tus proyectos

Imagina el siguiente escenario:
Tienes una elemento <select> con muchas opciones para elegir un color.

Tal vez en tu mente pienses hacer algo como lo siguiente:

// ❌import React from"react";

exportconst ColorOptions = () => {
  // Esto es muy cansado, repetitivo y no escala para nadareturn (
    <select><optionvalue="blue">blue</option><optionvalue="red">red</option><optionvalue="yellow">yellow</option><optionvalue="black">black</option><optionvalue="white">white</option><optionvalue="coffee">coffee</option><optionvalue="gray">gray</option><optionvalue="green">green</option></select>
	);
};

Pero esto significa desaprovechar las características más fundamentales de React.js. Una mejor solución sería crear una lista en JavaScript con los posibles valores de las opciones y de esta foma solo requerir una vez la lógica del elemento option.

// ✅import React from"react";

// De entrada vamos a recibir un array de colors// para iterar sobre el más tardeexportconst ColorOptions = ({ colors }) => {
  // Ahora esto escalaría de mejor manerareturn (
    <select>{colors.map((color) => (
        <optionvalue={color}>{color}</option>))}
    </select>);
};

Dónde aprender mejores prácticas para React

No te preocupes si alguna vez has usado estos antipatrones. Lo importante es que nunca pares de aprender para evitar cometer este tipo de tropiezos en tus próximos proyectos. 💪🏻

Aquí en Platzi puedes aprender las mejores prácticas para organizar, optimizar y mantener buenas prácticas en tu código JavaScript con React.js. Te recomiendo los siguientes cursos:

#NuncaParesDeAprender

Leonardo de los angeles
Leonardo de los angeles
LeoCode0

49166Puntos

hace 2 años

Todas sus entradas
Escribe tu comentario
+ 2
1
19145Puntos
2 años

Excelente blog @LeoCode0 ⭐