Cuando trabajas con sistemas reactivos, llega un momento en el que mantener múltiples efectos con expresiones repetidas se vuelve difícil de gestionar. Los signals derivados resuelven este problema al encapsular lógica dependiente de un signal dentro de funciones reutilizables, aprovechando la composición de las primitivas que ya existen en el sistema.
¿Cómo organizar efectos que dependen del mismo signal?
El punto de partida es un escenario donde varios createEffect dependen de un mismo signal, en este caso count. Cada efecto modifica una parte diferente del DOM [00:45]:
- Double: multiplica el valor actual del signal por dos y lo escribe en el elemento con ID
double.
- Is divisible by three: evalúa si el valor actual es divisible entre tres usando la operación módulo (
count % 3 === 0) y actualiza el elemento correspondiente.
Cada efecto incluye un console.log como debugger para verificar en consola lo que está sucediendo. Al ejecutar la aplicación, todos los efectos corren en la primera ejecución y luego se disparan cada vez que el signal count cambia, porque todos dependen de él.
Sin embargo, repetir expresiones como count * 2 o count % 3 === 0 en varios lugares no es ergonómico. Si la lógica cambia, hay que modificarla en cada punto donde se usa.
¿Qué son los signals derivados y por qué mejoran tu código?
Un signal derivado no es una nueva primitiva reactiva. Es el resultado natural de la composición de lo que ya se ha construido [03:20]. La idea es simple: encapsular la lógica derivada en una función independiente.
javascript
const doubleCounts = () => count() * 2;
const isDivisibleByThree = () => count() % 3 === 0;
Estas funciones actúan como signals derivados porque internamente ejecutan la lectura de un signal. Cuando se usan dentro de un createEffect, el sistema reactivo detecta automáticamente la dependencia.
Después de crear estas funciones, se reemplazan las expresiones directas en los efectos:
javascript
createEffect(() => {
console.log("double", doubleCounts());
document.getElementById("double").textContent = doubleCounts();
});
createEffect(() => {
console.log("is divisible by three", isDivisibleByThree());
document.getElementById("isDivisibleByThree").textContent = isDivisibleByThree();
});
Al probar la aplicación, todo sigue funcionando exactamente igual [04:10]. La diferencia está en la organización y mantenibilidad del código.
¿Por qué el sistema reactivo puede rastrear signals dentro de funciones anidadas?
Esta es la parte más potente del diseño. Cuando un efecto ejecuta doubleCounts(), internamente esa función ejecuta count(), que es la lectura de un signal [04:30]. El algoritmo del sistema reactivo detecta que, durante la ejecución de ese efecto, se leyó un signal específico.
El mecanismo funciona así:
- El efecto se registra como el listener activo.
- Al ejecutarse la función derivada, esta llama al signal original.
- El signal registra al efecto como dependiente.
- Cuando el signal cambia, notifica a todos sus dependientes, sin importar cuántos niveles de funciones haya en medio.
Como todo son funciones, no importa qué tan profundamente esté anidada la lectura del signal: el sistema siempre puede rastrear la dependencia. Esta es la ventaja fundamental de un diseño basado en funciones puras como unidad de composición.
¿Cuándo conviene usar signals derivados?
- Cuando la misma expresión derivada se usa en más de un lugar.
- Cuando quieres que el código sea más legible y declarativo.
- Cuando necesitas centralizar la lógica para facilitar cambios futuros.
¿Cuál es la diferencia con los memos?
Los signals derivados recalculan su valor cada vez que se ejecutan. Los memos, que son la siguiente primitiva reactiva, añaden una capa de optimización al cachear el resultado y evitar recálculos innecesarios en los ciclos de renderizado [05:15]. Es decir, el memo es la evolución natural del signal derivado cuando el rendimiento importa.
Si has trabajado con signals derivados y quieres entender cómo optimizar esas actualizaciones, comparte tu experiencia y cómo organizas tus efectos en tus proyectos.