Skip to content

property decorator #17

@ribrdb

Description

@ribrdb

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;
    });
  };
}

Metadata

Metadata

Assignees

No one assigned

    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