Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

317
Views
svelte: how can I declare two cyclically reactive variables?

I have two variables a and b which add up to 100. How do I set up a reactive declaration such that when a changes b changes to be 100 - a and vice versa? When I try something like

let total = 100;
$: a = total - b;
$: b = total - a;

I get a 'Cyclical dependency detected' error. Is there any way to get this done?

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

The problem comes from the fact that Svelte wants to sort the reactive blocks in the order they depend upon each other: it wants to compute those that are depended upon but have no dependencies first, to avoid unneeded computation... or getting trapped in a loop.

Furthermore, Svelte considers a dependency of a reactive expression any reactive variable that appear in it.

And so, the actual source of your error is that both variables a and b appears in both reactive expressions.

The solution is to remove from the reactive expressions the unneeded variable, that is the one that is assigned to. This can be done by moving the assignment to a function outside of the reactive block. Unfortunately, it's more verbose...

<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>
about 4 years ago · Juan Pablo Isaza Report

0

That does not work; Svelte does not allow this and this cycle cannot be resolved either. If you want a variable to be editable, you cannot declare it as reactive ($: x = ...). You can either reactively set regular variables with reactive statements/blocks or use events instead (see other answers).

The following is an explanation why this could not be resolved logically either.

Treating this like two equations with two unknowns you get this useless simplification:

a = total - b
b = total - a
b = total - (total - b)
b = total - total + b
b = b

You have to fix at least one of the values, otherwise all possible values are valid here.


You can also first normalize the equations:

a = total - b => a + b = total => a + b = total
b = total - a => b + a = total => a + b = total

As you can see, they are the same, so you actually have two unknowns and only one equation, so this is underspecified.

(Note that even if this would yield a valid solution, Svelte cannot solve systems of linear equations for you.)

about 4 years ago · Juan Pablo Isaza Report

0

Unless you need the values to update from programmatic changes, i would drop the reactive statements entirely and work with events instead: When one variable is adjusted by the user, update the other one.

<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>
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!