cover

Estos 3 React anti-patterns en los que podrías estar cayendo

author photo

Héctorbliss

@hectorbliss


Mira el video si prefieres:

robot logo saying hello

No te quedes atrás: Actualízate

Suscríbete para recibir información sobre nuevos frameworks, updates, eventos, tips, hacks y más.

React anti-patterns

Es bueno conocer las calles cerradas que tiene React, para saber por donde no deberías pasar.

Tal vez, si no te pones chido, ya andes caminando en veredas sinuosas. 🕋😱

Por eso, en este post te voy a mostrar y explicar:

Tres patterns comunes en React, que a toda costa, debes evitar.

§1. Inicializar el state usando propiedades 😟

Inicializar un estado con propiedades que se reciben desde el padre es un anti-pattern que seguro has usado. 🫣

Aunque también es uno que solemos romper voluntaria y conscientemente. 😎

Mira, te lo explico con el típico código de un contador. ⏲

import React, { useState } from 'react'; export default function Counter() { const [count, set] = useState(0); const handleClick = (num: number) => { set((val) => val + num); }; return ( <> <button onClick={() => handleClick(-1)}>-</button> {count} <button onClick={() => handleClick(1)}>+</button> </> ); }

Pero para mostrarte el anti-pattern vamos a declarar un nuevo prop en el componente <Counter>. Este nuevo prop es el número inicial del contador, así que lo emplearemos para inicializar el estado count.

import React, { useState } from 'react'; export default function Counter({ theCount = 0, }: { theCount: number; }) { const [count, set] = useState(theCount); const handleClick = (num: number) => { set((val) => val + num); }; return ( <> <button onClick={() => handleClick(-1)}>-</button> {count} <button onClick={() => handleClick(1)}>+</button> </> ); }

En este punto, tenemos dos fuentes distintas de verdad, lo que no es bueno, pues no es fácil distinguir cuál es el valor más confiable para usar en el programa y para mostrar al usuario.

Además, si la propiedad theCount cambia, el estado no se enterará, esto pone a tu aplicación en un estado inconsistente y podríamos estar creando bugs. 🪳 😫

¿Pero que pasa si la lógica de mi programa me obliga a usar una propiedad como valor inicial?

Una manera ser semántico(a), has que la variable comunique que el valor es solo inicial y que pronto se desactualizará, esto lo alcanzamos simplemente nombrando la variable como initialCount o defaultValue, el nombre que comunique mejor para ti. 🤓

Otra manera que me viene a la mente sería utilizar un useEffect para observar el cambio del prop y actualizar nuestro estado si el prop cambia.

useEffect(() => { set(theCount); }, [theCount]);

Si te es posible evitar este useEffect, mejor, incluso podrías utilizar un derived state. Aunque en ese caso, ya no deberías aumentar el contador con un estado local, convendría más que se usara un callback que permita cambiar los datos de origen, algo como un onClick.

§2. Usar el indice como key 😖

Utilizar la propiedad key correctamente es importante, no solo ayudamos a React a mantener los componentes en orden, también ayudamos a que el performance de nuestra aplicación sea el más optimo.

La propiedad key identifica de forma única a cada elemento en el DOM. React emplea esta propiedad para comprobar si el elemento es nuevo o debería actualizarse cuando el estado cambia.

Cuando no colocas la propiedad key en los elementos, por ejemplo al hacer un map() React mostrará un warning en la consola del navegador.

Pero aquí es donde aparece el anti-pattern, pues lo anterior tú ya lo sabías, solo que siempre usas el index, que recibes en el map, en la propiedad key.

¿Y qué, no es suficiente? 🤨

No blissmo, no es suficiente. 🫠

En este ejemplo, al dar clic al botón + agregaremos un nuevo elemento al principio de la lista.

import React, { useState } from 'react'; const more = ['Astro', 'Sveltekit', 'Qwik', 'Vite', 'Prisma']; export default function IndexMess() { const [tools, setTools] = useState(['Remix', 'Hugo']); const handleAdd = () => { const newTools = [more.pop(), ...tools]; setTools(newTools); }; return ( <> <ul> {tools.map((tool, index) => ( <li key={index}> {tool} <input type="text" name={tool} /> </li> ))} </ul> {tools.length < 7 && <button onClick={handleAdd}>Agregar más</button>} </> ); }

Observa que cada elemento incluye un input también, es input nos ayuda a desnudar el problema. ❌ ❤️‍🔥

indexBehaviour.gif

Puedes ver que cuando el nuevo elemento es agregado, los inputs dejan de coincidir.

Esto sucede así porque todo el array ha cambiado y React piensa que todos los elementos se han actualizado y que se ha agregado uno nuevo al final de la lista, por eso mantiene el input en su lugar. 🤯

¡Este comportamiento es prácticamente el mismo que tendríamos, si no utilizásemos un key en absoluto!

Para resolver este problema, debemos siempre emplear un valor único y estable, que identifique a un solo elemento. Puedes utilizar la propiedad id de tu modelo en la propiedad key, o usar una biblioteca como uniqid o nanoid.

👀 Este anti-pattern es muy común, ten paciencia con tus co-workers y explícales. 🤓

§3. Usar el spread operator para pasar props 😫

El profeta (es una broma) Dan Abramov ha hablado recientemente sobre un anti-pattern que deberías evitar a toda costa, un problema que ya levanta una alerta en la consola cuando incurrimos en él. Me refiero a usar la sintaxis de spread para evitar colocar las propiedades una por una a mano. 😟

<Avatar {...user} />

¡Oh no! ¿En serio? ¡A mí me encanta esta sintaxis! 😩

Esto provoca que React levante un warning sobre agregar atributos no estandarizados (non-standard) a un elemento del DOM.

Esta sintaxis funciona de maravilla y nos ahorra mucho trabajo, pero, existe una mejor forma para no escribir tanto y a la vez evitar la mala práctica de agregar atributos HTML desconocidos o que no existen.

const Avatar = ({ user }:{ user:User }) => ( <> <img src={user.photoURL} /> <p>{user.name}</p> // ... </> ); <Avatar user={user} />

Siempre puedes crear un prop para recibir todo el objeto, incluso así puedes tipar mejor tu componente con Typescript. ✅

Es bueno conocer las mejores prácticas, pero nunca debes perder de vista las malas.

Caer en estas prácticas comunes, por flojera o negligencia, minan calidad en tu oficio, te convierten en un programador promedio. Estas malas prácticas evitan que domines React. 🪓

Saber por qué algo es una mala práctica con la herramienta, te permite entender cómo es que React funciona, lo que, a su vez, te permite emplear la herramienta de forma muy efectiva. Por eso te invito a que de vez en cuando le des una vuelta a la documentación de React.

Abrazo. blissmo. 🤓

banner

¿Quieres mantenerte al día sobre los próximos cursos y eventos?

Suscríbete a nuestro newsletter

Jamás te enviaremos spam, nunca compartiremos tus datos y puedes cancelar tu suscripción en cualquier momento 😉

robot logo saying hello
facebook icontwitter iconlinkedin iconinstagram iconyoutube icon

© 2016 - 2023 Fixtergeek