lit icon indicating copy to clipboard operation
lit copied to clipboard

property decorator

Open ribrdb opened this issue 11 months ago • 0 comments

The nanostores best practices documentation says:

Reduce get() usage outside of tests get() returns current value and it is a good solution for tests. But it is better to use useStore(), $store, or Store#subscribe() in UI to subscribe to store changes and always render the actual data.

However it seems like if you use the current decorators or mixin you still have to call get in your render method. What about adding a property decorator:

/**
 * Decorator that binds a property to a nanostore.
 * The property will be updated whenever the store changes (and requestUpdate will be called).
 *
 * @example
 * ```ts
 * class MyElement extends LitElement {
 *   @store($count)
 *   private count!: number;
 *
 *   render() {
 *     return html\`Count: \${this.count}\`;
 *   }
 * }
 * ```
 */
export function store<T>(store: Store<T>) {
  return function(target: any, propertyKey: string): void {
    // Create a unique symbol for storing the controller
    const controllerKey = Symbol();

    // Define the property
    Object.defineProperty(target, propertyKey, {
      get(this: ReactiveElement) {
        return (this as any)[controllerKey]?.value;
      },
      configurable: true,
      enumerable: true
    });

    // Add initializer to set up the controller
    (target.constructor as typeof ReactiveElement).addInitializer(function(element: ReactiveElement) {
      const controller = new StoreController(element, store);
      (element as any)[controllerKey] = controller;
    });
  };
}

ribrdb avatar Apr 06 '25 02:04 ribrdb