cover

¿Por qué todo mundo está loco por las señales, y cómo usarlas en React?

author photo

Héctorbliss

@hectorbliss


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.

Las señales son la moda. No importa siquiera si comprendemos completamente el problema que resuelven, todo mundo las está usando, por tanto, queremos usarla y hay que seguir a la multitud, ¿no?

Pero yo te propongo que: en vez de solo repetir, comprendamos. 🤓

TL;DR

Si estás buscando cómo implementarlas ya mismo, la mejor opción que tengo para ofrecerte es npm i @preact/signals-react. Pero si lo que realmente quieres es comprenderlas y saber por qué sería buena idea utilizarlas, entonces vamos a hacerlo fácilmente con 4 pedacitos de información útil:

Pedacito #1: ¿Qué es una señal?

Una señal es un objeto (como todo en JavaScript). Pero este objeto tiene un value, este valor, puede ser observado en espera de cambios.

Una característica importante de las señales es que no están confinadas a un componente, las señales son independientes y pueden compartir su value a través de diferentes niveles y componentes sin tener que detonar un «re-render» de todo el árbol como con Context. Sí, las señales pueden sustituir por completo a Context.

En resumen:, una señal es un tipo de estado, que no está atado a ningún componente, actualizando específicamente el UI necesario sin el costoso re-renderizado.

Pedacito #2: effect vs signal

Hagamos un pequeño experimento. Este es un componente que cualquiera de nosotros escribiríamos:

import * as React from 'react'; export default function App() { console.log('Re-renderizando'); const [state, set] = React.useState(0); const handleClick = () => { set(state + 1); }; return ( <div> <h1>Hello Blissmo!</h1> <p>¡Let's use signals!</p> <h1>Estado: {state}</h1> <button onClick={handleClick}>Súmale 1</button> </div> ); }

re-rendering with state Este es el componente más normal del mundo, ¿cierto? Esto es lo que tenemos siempre en nuestros componentes. Bueno, pues cada que presionamos el clic, el componente se vuelve a renderizar por completo, puedes hacer la prueba tú mismo.

👀 Aquí puedes experimentar con el código en tiempo real.

Vamos a hacer otro ejemplo, ahora con useEffect.

Supongamos que queremos tener un contador en nuestro componente. Escribiríamos algo así:

import * as React from 'react'; export default function App() { const [state, set] = React.useState(0); React.useEffect(() => { setInterval(()=>set(state + 1), 1000); }, []); return ( <div> <h1>Hello blissmo!</h1> <p> El tiempo vuela. 💸 ¡No vendas tu tiempo! <br /> Mejor vuela con él. </p> <h1>Time: {state}</h1> </div> ); }

Si pruebas este código aquí te darás cuenta de que el valor está congelado. Esto porque state ha quedado guardado en memoria y cada que el intervalo se repite, el valor de state es el mismo, pues está «memoizado».

Si agregamos la eliminación del intervalo podríamos evitar este congelamiento.

import * as React from 'react'; export default function App() { console.log('Re-render'); const [state, set] = React.useState(0); const interval = React.useRef<null | ReturnType<typeof setInterval>>(); React.useEffect(() => { interval.current = setInterval(() => set(state + 1), 1000); return () => clearInterval(interval.current); }, [state]); return ( <div> <h1>Hello blissmo!</h1> <p> El tiempo vuela 💸, ¡no vendas tu tiempo! <br /> Mejor vuela con él. </p> <h1>Time: {state}</h1> </div> ); }

useEffect interval Pero de nuevo, estamos re-renderizando y peor aún, estamos reconstruyendo el intervalo cada vez.

¡Estos cambios ahora están tomando incluso más de un segundo en cambiar! Estamos haciendo trabajar mucho a este componente. 😰

Pedacito #3: Opciones en señales

Vamos a intentar resolver este problema de renderizado (que no sabíamos que teníamos, pues así es como React funciona) con señales.

Existen muchas opciones para trabajar con estados con herramientas conocidas como Redux, Rematch, Zustand o incluso con estrategias novedosas como la atómica con Recoil o Jotai.

Pero a mí me encanta lo simple, por eso, vamos a analizar la que me parece más simple y elegante y que no requiere ningún tipo de configuración especial para usarla ya mismo con nuestros proyectos React.

Estoy hablando de @preact/signals-react

Instalación: npm i @preact/signals-react

Las Preact signals son una forma de expresar un estado.

Este estado se asegura de que nuestra app se mantenga rápida sin importar cuan compleja pueda ser. Las señales de Preact son mi recomendación porque no solo están construidas sobre los fundamentos de que Ryan Carniato muy amablemente nos explica en su blog, también están especialmente optimizadas para trabajar sobre el Virtual Dom.

Pedacito #4: Resolviendo el problema

Vamos, pues, a instalar e implementar signals en nuestro ejemplo y ver si podemos evitar el re-renderizado y de paso optimizar nuestra app.

Comenzamos instalando npm i @preact/signals

import * as React from 'react'; import { signal } from '@preact/signals-react'; const count = signal(0); export default function App() { console.log('re-render'); const handleClick = () => count.value++; return ( <div> <h1>Hello Blissmo!</h1> <p>Valor de la señal: {count}</p> <button onClick={handleClick}>Súmale 1</button> </div> ); }

Hay que notar un par de cosas aquí. La primera es que la señal se importa desde la biblioteca @preact/signals-react que es un paquete independiente de Preact y no necesitamos tener instalado preact. Lo segundo es que declaramos nuestra señal fuera del componente, con esto sabemos que podríamos tener esta señal en cualquier otro archivo y compartirlo con toda nuestra app. Por último, podemos observar que hemos resuelto nuestro problema, pues nuestro componente ya no renderiza cada que el valor del estado se actualiza. 🎉 Mira cómo funciona en vivo aquí

signals implemented

Conclusion

Yo creo que el equipo de React no tarda en publicar su propia implementación de signals, pues ya todo mundo tiene la suya propia (Angular, Qwik, Solid, Vue, Svelte etc.) menos React.

Pero por ahora Preact que nació desde el principio como una alternativa «más simple y ligera» a React, nos salva el día, incluso te recomendaría que le echaras un ojo 👀 a la documentación, quién sabe, igual y te migras por completo a Preact una vez conociendo su filosofía.

¿Te gustaría saber más de Preact en mi blog?

Algo que me encanta de las señales de Preact es: que las puedes usar sin llamar al atributo value como es necesario con otras herramientas. Puedes simplemente usar <p>{count}</p> en vez de <p>{count.value}</p>

Mientras tanto, ya puedes utilizar este nuevo conocimiento en tu día a día, es hora de sustituir useState por signal. 🤯

Abrazo. bliss.

Enlaces relacionados

Introducing signals

Preact signals

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