Tengo dos variables a y b que suman 100. ¿Cómo configuro una declaración reactiva de modo que cuando a cambie b cambie a 100 - a y viceversa? Cuando intento algo como
let total = 100; $: a = total - b; $: b = total - a;Aparece el error "Dependencia cíclica detectada". ¿Hay alguna manera de hacer esto?
El problema proviene del hecho de que Svelte quiere ordenar los bloques reactivos en el orden en que dependen unos de otros: primero quiere calcular aquellos de los que se depende pero que no tienen dependencias, para evitar cálculos innecesarios... o quedar atrapado en un círculo.
Además, Svelte considera una dependencia de una expresión reactiva cualquier variable reactiva que aparezca en ella.
Entonces, la fuente real de su error es que ambas variables a y b aparecen en ambas expresiones reactivas.
La solución es quitar de las expresiones reactivas la variable innecesaria, que es la que está asignada. Esto se puede hacer moviendo la asignación a una función fuera del bloque reactivo. Desafortunadamente, es más detallado...
<script> let total = 100; let a = 0 let b = 0 const setA = () => { // the assignment to a (or b in the other function) are still // reactive, of course, but Svelte won't propagate changes to // variable that are assigned their current value, so this // will break the loop a = total - b } const setB = () => { b = total - a } $: setA(total - b); $: setB(total - a); </script> <pre> a: {a} b: {b} </pre> <label> a <input type="number" bind:value={a} /> </label> <label> b <input type="number" bind:value={b} /> </label>Eso no funciona; Svelte no permite esto y este ciclo tampoco se puede resolver. Si desea que una variable sea editable, no puede declararla como reactiva ( $: x = ... ). Puede establecer reactivamente variables regulares con declaraciones/bloques reactivos o usar eventos en su lugar (ver otras respuestas).
La siguiente es una explicación de por qué esto tampoco podría resolverse lógicamente.
Tratando esto como dos ecuaciones con dos incógnitas, obtienes esta simplificación inútil:
a = total - b b = total - a b = total - (total - b) b = total - total + b b = bDebe corregir al menos uno de los valores, de lo contrario, todos los valores posibles son válidos aquí.
También puedes normalizar primero las ecuaciones:
a = total - b => a + b = total => a + b = total b = total - a => b + a = total => a + b = totalComo puede ver, son lo mismo, por lo que en realidad tiene dos incógnitas y solo una ecuación, por lo que está subespecificada.
(Tenga en cuenta que incluso si esto arrojara una solución válida, Svelte no puede resolver sistemas de ecuaciones lineales por usted).
A menos que necesite que los valores se actualicen a partir de cambios programáticos, eliminaría las declaraciones reactivas por completo y trabajaría con eventos en su lugar: cuando el usuario ajusta una variable, actualice la otra.
<script> const total = 100; let a = total; let b = 0; </script> a: {a} <br> b: {b} <label> a <input type="number" bind:value={a} on:input={() => b = total - a} /> </label> <label> b <input type="number" bind:value={b} on:input={() => a = total - b} /> </label>