Attach Redux store state and Reselect selectors to properties in LitElement with the @watch()
decorator or a static watch
getter.
npm i lit-redux-watch
We generate API documentation with TypeDoc.
This example uses TypeScript with decorators to register properties with watchers. Decorators are an experimental feature but can be used by enabling them in your tsconfig.json
. More information can be found in the TypeScript Documentation.
The TC39 proposed decorators which are currently in Stage 2 will be supported in the future.
import {LitElement, html} from 'lit-element';
import {connect, watch} from 'lit-redux-watch';
import {store} from './store'; // Your redux store
class UserPage extends connect(store)(LitElement) {
@watch('user.name')
userName?: string;
render() {
return html`
<div>Name: ${this.userName}</div>
`;
}
}
import {LitElement, html} from 'lit-element';
import {connect} from 'lit-redux-watch';
import {store} from './store'; // Your redux store
class UserPage extends connect(store)(LitElement) {
static get watch() {
return {
userName: 'user.name'
}
}
render() {
return html`
<div>Name: ${this.userName}</div>
`;
}
}
To use lit-redux-watch in a class, use the connect
mixin.
class MyElement extends connect()(LitElement) {}
class MyElement extends connect(store)(LitElement) {}
class MyElement extends connect(store, options)(LitElement) {}
When no store is provided via connect
one must be provided via static get watch
/@watch
.
To create a watching property, use the @watch
decorator.
@watch('user.firstName')
userFirstName?: string;
@watch('user.lastName', options)
userLastName?: string;
@watch('user.email', store)
userEmail?: string;
@watch('user.address', options, store)
userAddress?: string;
// Or a function
@watch((state) => state.user.phone || state.user.mobile)
userPhoneNumber?: string;
// Or a reselect selector
@watch(userLanguagesSelector)
userLanguages?: string[];
See the sections on sources and options for more information about what sources and options can be used.
To create a watching property, use the static watch
getter.
static get watch() {
return {
userFirstName: {
source: 'user.firstName',
store: store,
// Options are added in the same object
noInit: true,
transform: (next) => next.trim(),
}
}
}
Options and stores provided via static get watch
/@watch
override those provided in the connect
mixin.
A simple path-string can be used as a source.
@watch('shop.items')
shopItems?: ShopItem[];
Path-strings are like object paths, so the above maps to:
store.getState().shop.items
The difference is that if the string-path can not be traversed all the way undefined
is returned instead of an error being thrown.
Instead of a path-string a function can also be used as source.
@watch((state) => state.user.firstName)
userFirstName?: string;
The function gets called with the store state as the first parameter and should return the value for lit-redux-watch to use.
Reselect selectors can also be used as a source since they return a function compatible with the pattern mentioned in Function source.
Simply create a selector...
const shopItemsSelector = (state) => state.shop.items;
const subtotalSelector = createSelector(
shopItemsSelector,
items => items.reduce((acc, item) => acc + item.value, 0),
);
...and use it as your watch source.
@watch(subtotalSelector)
subtotal?: number;
For more information about Reselect see the reselect documentation.
These are the available options for watchers.
{
/**
* Override the default strict === compare function. If you need deep
* equal you can use epoberezkin/fast-deep-equal.
*/
compare: function(a, b) {
return a === b;
},
/**
* Indicates whether the value should be loaded from redux on init. By
* default the value will be loaded when the property is initialized
* but this can be disabled by setting `noInit: true`.
*/
noInit: false,
/**
* A function that is called when a new value is found that should
* return a boolean to indicate whether the value should be updated.
*/
shouldUpdate: function(nextValue, oldValue, source) {
return nextValue !== "";
},
/**
* A function that is called when the value is updated that allows
* the new value to be transformed. Note: this does not transform the
* value that is passed as the second argument of the shouldUpdate and
* transform functions.
*/
transform: function(nextValue, oldValue, source) {
return nextValue.trim();
}
}
lit-redux-watch is inspired by jprichardson/redux-watch and the property registration from Polymer/lit-element
- The TC39 proposed decorators which are currently in Stage 2 will be supported in the future.
- Maybe dispatching actions back to redux on property
set
will be added. Currently looking into this.
Made by Paul Gerarts