Skip to content

$derived.by destructor support (Svelte 5) #13249

@timephy

Description

@timephy

Describe the problem

I use $derived or $derived.by to "couple" state widely in my app. For example like so:

    const baseObj = $state(...)
    const derivedObj = $derived.by(() => {
        // Not possible here, because it cannot reference itself
        // derivedObj.destroy()

        const _obj = new DerivedObj(baseObj)
        _obj.setup()
        return _obj
    })

The baseObj might not be a primitive type, but rather a class with "complex behaviour", for example in many cases a rxjs.Observable inside. When I create a new DerivedObj(baseObj) from that baseObj, then I might want to setup listeners/subscriptions on baseObj, which should be unsubscribed/destroyed on the old derivedObj, when it is recreated by $derived.

This raises the need for a destructor function.

Describe the proposed solution

$effect currently has something like "destuctor support": (see Preview Docs)

You can return a function from $effect, which will run immediately before the effect re-runs, and before it is destroyed (demo)."

Therefore it might make sense to implement it similarly for $derived.

There should be a functionality that does this (sentence from $effect docs reformulated):

You can specify a "destuctor" function, which will run immediately before the derived.by re-runs, and before it is destroyed.

I could imagine using it like so:

    const baseObj = $state(...)
    const derivedObj = $derived.by(
        // "constructor"
        () => {
            const _obj = new DerivedObj(call, modalVC)
            _obj.setup()
            return _obj
        },
        // "destructor"
        () => {
            derivedObj.destroy()
        }
    )

The destructor should be run immediately before $derived reruns and creates a new object from the source state. And before $derived is destroyed, so that the destructor is also called when a component is destroyed, otherwise we have to repeat the destructor inside onDestroy(() => derivedObj.destroy()), which would be repeating every time.

Importance

i cannot use svelte without it

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions