sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.21k stars 4.09k forks source link

In class syntax, you cannot create non-reactive variables. #11670

Closed XIYO closed 3 months ago

XIYO commented 3 months ago

Describe the bug

In class syntax, if you declare non-reactive (regular) variables alongside reactive ones, they will be updated together in sync with the updates of the reactive variables (wait for tick).

Reproduction

https://github.com/sveltejs/svelte/assets/27078637/7c706b23-b9f8-45cd-b7f7-45fc6035af36

Hello, I used the GPT4 translator. Please let me know if there are any awkward sentences.

It seems there are definite issues with non-reactive variables in class syntax.

There are also some issues with the functional syntax:

  1. If you use getters to export variables without making them reactive, they become non-reactive (regular) variables. Would it not be safer to treat exporting reactive variables as non-reactive as a compile error? Reactive variables can already be exported using $state().snapshot(a). Could such allowances not lead to confusion for developers?
  2. Similar to class syntax, when regular variables are exported using getters, they become reactive (responding to ticks).

It's possible that I may have misunderstood Svelte syntax. If so, I would appreciate your understanding.

https://github.com/XIYO/svelte-class-state-bug

Logs

No response

System Info

svelte5.next.136

  System:
    OS: Windows 11 10.0.22621
    CPU: (8) x64 Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
    Memory: 16.22 GB / 31.93 GB
  Binaries:
    Node: 21.7.1 - C:\Program Files\nodejs\node.EXE
    npm: 10.5.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.1.1 - C:\Program Files\nodejs\pnpm.CMD
  Browsers:
    Edge: Chromium (123.0.2420.97), ChromiumDev (125.0.2518.0)
    Internet Explorer: 11.0.22621.3527

Severity

blocking an upgrade

dummdidumm commented 3 months ago

You're running into an edge case here with the rerender heuristic. Svelte batches identifiers (foo) and member expressions (foo.bar) into one render effect to save memory and for better performance. The thought process is that identifiers cannot have side effects, and getters should never have. In your case, everything's in one render effect, but it will only update if you actually modify a reactive variable. The last non-state is never updated because Svelte can detect that it's a non-reactive variable (because it's in scope and can be statically analyzed). Closing as this heuristic was chosen deliberately.

XIYO commented 3 months ago

@dummdidumm

I have understood your message through the translation.

In that case, how can we create non-reactive variables using class syntax? (It seems like you mentioned it's not possible...) With functional syntax, non-reactive variables can be created and simply returned.

Am I correct in understanding that there is a difference in declaring non-reactive syntax between functional and class syntax, and that I should use functional syntax when necessary? (In other words, there are limitations with class syntax.)

dummdidumm commented 3 months ago

The variable is not reactive in the sense that it will never trigger an update somewhere else. But if that variable happens to be read together with other variables that are in a reactive context and therefore rerun, then the current value will be used.