element icon indicating copy to clipboard operation
element copied to clipboard

feat: new `@memo` and `@effect` decorators from updated classy-solid

Open trusktr opened this issue 2 months ago • 0 comments

See classy-solid docs for info.

Small example:

@element
class MyEl extends Element {
  @signal a = 1
  @signal b = 2

  @memo get sum() { return this.a + this.b }

  @effect logSum() {
    console.log('sum:', this.sum)
  }
}

The Element base class will ensure that effects will be cleaned up on disconnect, and restarted on connect by calling classy-solid's stopEffects() and startEffects() functions in connectedCallback and disconnetedCallback.

BREAKING:

  • The stopEffects() method of @lume/element's Element base class is removed.
    • migration: If you were relying on stopEffects() for customized management of starting and stopping effects, instead use the Effects class from classy-solid to manage your own set of effects separately from those that the Element base class manages. Old code:
      // ...imports...
      
      @element
      class MyEl extends Element {
        connectedCallback() {
          super.connectedCallback()
          this.#createEffects()
        }
      
        // Example: method that starts all effects.
        #createEffects() {
          this.createEffect(() => {...}) // method from Element base class.
          this.createEffect(() => {...}) // method from Element base class.
        }
      
        // Example: custom restarting of effects for some reason.
        restartEffects() {
          this.stopEffects() // method from Element base class.
          this.#createEffects()
        }
      }
      
      New code:
      // ...imports...
      import {Effects} from 'classy-solid'
      
      @element
      class MyEl extends Element {
        #myEffects = new Effects()
      
        connectedCallback() {
          super.connectedCallback()
          this.#createEffects()
        }
      
        disconnectedCallback() {
          super.disconnectedCallback()
          this.#myEffects.clearEffects()
        }
      
        // Example: method that starts all effects.
        #createEffects() {
          this.#myEffects.createEffect(() => {...})
          this.#myEffects.createEffect(() => {...})
        }
      
        // Example: custom restarting of effects for some reason.
        restartEffects() {
          this.#myEffects.clearEffects() // Use the new `Effects.clearEffects()` method.
          this.#createEffects()
        }
      }
      
      Any effects created with @effect or this.createEffect() are managed by the Element base class. The new clearEffects() method from classy-solid's Effectful() mixin or Effects class deletes previous effects, and the createEffect() method will create new ones. The stopEffects() method from classy-solid still exists (that's what the method from the Element base class used to be), but it does not delete effects, and instead holds a list of all previously created effects such that the new startEffects() method can be used to start all effects after they've been stopped. The above code can also be writte like so, without re-creating all the effects: New code, 2nd version:
      // ...imports...
      import {Effects} from 'classy-solid'
      
      @element
      class MyEl extends Element {
        #myEffects = new Effects()
      
        constructor() {
          super()
          this.#myEffects.createEffect(() => {...})
          this.#myEffects.createEffect(() => {...})
        }
      
        connectedCallback() {
          super.connectedCallback()
          this.#myEffects.startEffects()
        }
      
        disconnectedCallback() {
          super.disconnectedCallback()
          this.#myEffects.stopEffects()
        }
      
        // Example: custom restarting of effects for some reason.
        restartEffects() {
          this.#myEffects.stopEffects()
          this.#myEffects.startEffects()
        }
      }
      
      Restarting effects like this is not recommended unless the component has sub-features that need to be started and stopped independently of the element being connected into the DOM.

trusktr avatar Dec 14 '25 23:12 trusktr