Skip to content

reacitivity broken when using classes #15663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mithrendal opened this issue Apr 1, 2025 · 6 comments
Closed

reacitivity broken when using classes #15663

mithrendal opened this issue Apr 1, 2025 · 6 comments

Comments

@mithrendal
Copy link

mithrendal commented Apr 1, 2025

Describe the bug

state rune reactivity does not work when using an object which has been "newed" from an Java or Typescript class

<script>
    class MyJSclass {
       count = 0;
    }
    let jsclazz = $state(new MyJSclass());
</script>
    
counter { jsclazz.count } 
    
<button onclick={()=>jsclazz.count++}>increase</button>

when the rune declaration

    let jsclazz = $state(new MyJSclass());  

is changed to

    let jsclazz = $state({...new MyJSclass()});  

it works as expected.

Reproduction

<script>
    class MyJSclass {
      count = 0;
    }
    let jsclazz = $state(new MyJSclass());
</script>
    
counter { jsclazz.count } 
    
<button onclick={()=>jsclazz.count++}>increase</button>

Logs

System Info

any svelte5 system, online REPL or freshly scaffolded svelte5 app

Severity

annoyance

@brunnerh
Copy link
Member

brunnerh commented Apr 1, 2025

Related/duplicate of:

@paoloricciuti
Copy link
Member

Currently it work as expected and as @brunnerh said it's a duplicate of a feature request, therefore closing...thanks for reporting!

@mithrendal
Copy link
Author

mithrendal commented Apr 1, 2025

...thanks for reporting!

@paoloricciuti Thank you for the info , that the behavior is intended and that it works as expected !

So I learned that in order to get the reactivity on JS-Objects created from classes (i.e. non-POJOs) the Svelte5 recommended way

is either

   class MyClass{
      count = $state(0);
   }
   let my_obj = $state(new MyClass());  

or

  let my_obj = $state( {...new MyClass()} as MyClass )

correct ?

The latter code fragment does not need any modification of the class.

Do you think that it maybe makes sense to include it in the class section of https://svelte.dev/docs/svelte/$state ?

@paoloricciuti
Copy link
Member

Honestly spreading classes is something very risky and this also negates the benefits of using classes in the first place because you will end up with a POJO anyway. So i would stick with using state within classes

@mithrendal
Copy link
Author

@paoloricciuti yes I see now. 🙈 You are right, better not mention the spreading in the svelte docs. It is too risky depending in the way how you use classes.

We are fine in using POJOs. We only make classes for data structures anyway so we also can use POJOs instead. We initially used classes for data structures because it is a typescript project and it felt to us as the natural typescript way of defining them and svelte4 did not complain. Maybe better as spreading is the modern structuredClone() (only in modern browsers) which deep copies instead of shallow and therefore avoids unwanted mutation.

Anyway thanks for pinging back. ❤️Loving your work on svelte5 so far.

@brunnerh
Copy link
Member

brunnerh commented Apr 2, 2025

If you only have POJOs you don't need any of that, they can just be mutated directly and will be reactive (via proxies).

Also, spreading plain objects usually is not as much of an issue, at least you will not lose the prototype in the process (it will just be a plain object before and after). You will lose custom getters and setters, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants