Giter Site home page Giter Site logo

lit-watch's Introduction

lit-watch

MIT NPM

Create decorators from redux stores and observables like RxJS objects.

Install

npm i lit-watch

Usage

You can create a decorator from any observable:

import { createWatcher } from 'lit-watch';

// Create a @watch decorator
export const watch = createWatcher(observable);

Use it in your LitElements:

import { html, LitElement } from 'lit';
import { watch } from './watch';

export class Account extends LitElement {
    @watch((state) => state.user.fullName)
    public user!: string;

    render() {
        return html`
            Signed in as ${this.user}
        `;
    }
}

NOTE: Use public (do not use private / protected)

One of the goals of lit-watch was to force type-checking between the decorator output and the property. Due to a TypeScript limitation, however, the properties with a watching decorator have to be public. In a sense, from the scope of the decorator, we are accessing the class type from the outside, . Because any private or protected property will be invisible to the decorator, you may see a cryptic error when using these on any non-public properties.

NOTE: Do not set a default value

The decorator redefines the property with an accessor (get), so setting default values does not work. You can add a default in your select function by using a nullish coalescing operator (??).

// Do
@watch((state) => state.some)
public some!: string;

// Do not
@watch((state) => state.some)
public some: string = 'default value';

// For defaults
@watch((state) => state.some ?? 'default value')
public some!: string;

By using !, we are letting TypeScript know that this value will be set, so we do not get any errors while using the --strictPropertyInitialization option.

NOTE: Do not use before connectedCallback

Do not use lit-watch values in your constructor, as value accessors are initialized and subscribed in the connectedCallback and will unsubscribe in the disconnectedCallback.

Creating a decorator from a redux store

Since redux is interoperable with observable/reactive libraries you can watch redux stores like any other observable.

Create the decorator from your redux store:

import { createWatcher } from 'lit-watch';
import { store } from './store';

// Create a @watch decorator
export const watch = createWatcher(store);

Filtering, transforming and combining data with reselect

You can use reselect's createSelector to create complex queries.

One of the benefits of using reselect over writing your own function is that reselect uses memoization to prevent unnecessary updates when the source data has not been changed.

For more information about reselect, see the reselect docs.

The examples below show some inline use of reselect, but you are free to pass your selectors from elsewhere.

Filtering

@watch(createSelector(
    (state) => state.messages,
    (messages) => {
        // This only runs if state.messages changed
        return messages.filter((item) => !item.read);
    }
))
public unread!: Message[];

Transforming

@watch(createSelector(
    (state) => state.cart.items,
    (items) => {
        // This only runs if state.cart.items changed
        return items.reduce(
            (sum, item) => sum + item.price,
            0,
        );
    }
))
public total!: number;

Combining

@watch(createSelector(
    (state) => state.user.name,
    (state) => state.user.cart.items.length,
    (user, items) => {
        // This only runs if either state.user.name, or
        // state.user.cart.items.length changed (or both)
        return `${user} has ${items} in their cart`;
    }
))
public message!: string;

Multiple watchers

If you are planning on watching multiple observables, or maybe even multiple stores, it might make sens to name your decorators something more descriptive.

// @watchStore()
export const watchStore = createWatcher(store);

// @watchPrice()
export const watchPrice = createWatcher(priceObservable);
export class Account extends LitElement {
    @watchStore((state) => state.item.description)
    public description!: string;

    @watchPrice()
    public price!: number;

Use with Observables and RxJS

You can create watchers from RxJS (and other) observables by passing them to createWatcher.

const watchClimate = createWatcher(climateObservable);

License

MIT

Made by Paul Gerarts

lit-watch's People

Contributors

gerarts avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

rweave

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.