svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Changed $state randomly doesn't update the UI

Open jnsmalm opened this issue 1 year ago • 5 comments

Describe the bug

I have a piece of html below ("totalWin" is a piece of $state on the "bet"-object) and most of the time the value updates as expected:

<div class="flex flex-col justify-center items-center">
  <div>
    Test
  </div>
  <div
    class={`text-xl font-normal`}
  >
    {currency.formatCurrency(bet.totalWin)}
  </div>
</div>

But sometimes (randomly?) it doesn't reflect the new value of "totalWin" state (on iOS Safari). I debugged this and removed more and more code until I found what caused it. If I instead change to the code to below it works always (the only changed thing is that I removed the "Test" text from the sibling html node):

<div class="flex flex-col justify-center items-center">
  <div>
   
  </div>
  <div
    class={`text-xl font-normal`}
  >
    {currency.formatCurrency(bet.totalWin)}
  </div>
</div>

How and why, you have any idea?

Reproduction

Sorry, this is a pretty big project.

Logs


System Info

System:
    OS: macOS 15.4.1
    CPU: (11) arm64 Apple M3 Pro
    Memory: 316.48 MB / 18.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.12.0 - ~/.nvm/versions/node/v22.12.0/bin/node
    npm: 10.9.0 - ~/.nvm/versions/node/v22.12.0/bin/npm
    bun: 1.0.29 - ~/.bun/bin/bun
  Browsers:
    Chrome: 135.0.7049.115
    Safari: 18.4
  npmPackages:
    svelte: ^5.0.0 => 5.28.2

Severity

blocking an upgrade

jnsmalm avatar Apr 25 '25 15:04 jnsmalm

Is this reproduction enough to accurately mirror your use case: https://svelte.dev/playground/1f32901c94ab448683eda243ff664b9e?version=5.28.2? If so, I can't see any issue there, even on iOS Safari.

michal-weglarz avatar Apr 25 '25 18:04 michal-weglarz

Thanks, but I guess it doesn't because your scenario works. I can also make it work my switching the two divs like this:

<div class="flex flex-col justify-center items-center">
  <div
    class={`text-xl font-normal`}
  >
    {currency.formatCurrency(bet.totalWin)}
  </div>
  <div>
    Test
  </div>
</div>

Feels like it has something to do with html hierarchy in some rare cases.

jnsmalm avatar Apr 25 '25 19:04 jnsmalm

Don't know how to reproduce it in a simpler way. but pretty sure it's a bug in Svelte. I solved it by creating a component for just the "totalWin" which seems to work fine:

<script lang="ts">
  import type { BetService } from "../service/bet-service.svelte";
  import type { CurrencyService } from "../service/currency-service";

  interface Props {
    bet: BetService<unknown>;
    currency: CurrencyService;
  }

  let { bet, currency }: Props = $props();
</script>

<span>{currency.formatCurrency(bet.totalWin)}</span>

jnsmalm avatar Apr 25 '25 19:04 jnsmalm

Seems it could also be solved by just adding a key around it, maybe this could give you a clue about the bug?

{#key bet.totalWin}
  {currency.formatCurrency(bet.totalWin)}
{/key}

jnsmalm avatar Apr 25 '25 19:04 jnsmalm

Without a reproduction we have no clue sorry...can you try to slim down your project to provide one?

paoloricciuti avatar May 23 '25 21:05 paoloricciuti