2.0.1 • Published 6 years ago
@laps.no/stencil-redux-decorators v2.0.1
State and Action map decorators for @stencil/redux
Reduce boilerplate code when working with redux in Stencil:
Examples
Before/after example
The following code is the example code from @stencil/redux
Before - without decorators
import { Component, State, Prop } from '@stencil/core';
import { Store, Action } from '@stencil/redux';
@Component({
tag: 'my-component',
styleUrl: 'my-component.scss'
})
export class MyComponent {
@Prop({ context: 'store' }) store: Store;
@State() name: string;
changeName: Action;
componentWillLoad() {
this.store.mapStateToProps(this, (state) => {
const {
myReducer: { name }
} = state;
return {
name
}
});
this.store.mapDispatchToProps(this, {
changeName
});
}
doNameChange(newName: string) {
this.changeName(newName);
}
}
After - with decorators
import { Component, State, Prop } from '@stencil/core';
import { ReduxState, ReduxDispatch } from '@laps.no/stencil-redux-decorators';
import { Store, Action } from '@stencil/redux';
@Component({
tag: 'my-component',
styleUrl: 'my-component.scss'
})
export class MyComponent {
@Prop({ context: 'store' }) store: Store;
@ReduxState('myReducer.name')
@State() name: string;
@ReduxDispatch('APP_SET_NAME')
changeName: Action;
doNameChange(newName: string) {
this.changeName({ name: newName });
}
}
Menu Example
export class MenuComponent {
/* store property is required */
@Prop({ context: 'store' })
store: Store
/* map state = { menu: { isCollapsed }} to this.isCollapsed */
@State()
@ReduxState('menu.isCollapsed')
isCollapsed: boolean
@ReduxDispatch({ type: 'TOGGLE_MENU' })
toggleMenu: Action
render() {
const innerMenuClass = this.isCollapsed ? 'inner collapsed' : 'inner';
return (
<div class="menu">
<div class={innerMenuClass}>
...
</div>
<button onClick={() => this.toggleMenu()}>
TOGGLE_MENU
</button>
</div>
);
}
}
Calculate state path from properties
export class XYComponent {
/* store property is required */
@Prop({ context: 'store' })
store: Store
@Prop()
x = "foo"
@Prop()
y = "bar"
@State()
@ReduxState('graph.[x].[y].value')
value: boolean
/*
{
graph: {
foo: {
bar: {
value // <--
}
}
}
}
*/
}
Map action with predefined data:
export class MessageComponent {
/* store property is required */
@Prop({ context: 'store' })
store: Store
/* Map action with predifned data */
@ReduxDispatch({ type: 'SEND_MESSAGE', message: 'Predefined message', color: 'red' })
sendPredefinedMessage: Action
render() {
<button onClick={() => this.sendPredefinedMessage()}>
Send predefined message
</button>
}
}
Result:
{
"type": "SEND_MESSAGE",
"message": "Predefined message",
"color": "red"
}
Dispatch action with custom data:
export class MessageComponent {
/* store property is required */
@Prop({ context: 'store' })
store: Store
/* Map action */
@ReduxDispatch({ type: 'SEND_MESSAGE' })
sendMessage: Action
render() {
<button onClick={() => this.sendMessage({ message: 'Very important message', color: 'blue'})}>
Send important Message
</button>
}
}
Result:
{
"type": "SEND_MESSAGE",
"message": "Very important message",
"color": "blue"
}
Override predefined data:
export class MessageComponent {
/* store property is required */
@Prop({ context: 'store' })
store: Store
/* Map action with predifned data */
@ReduxDispatch({ type: 'SEND_MESSAGE', color: 'red' })
sendMessage: Action
render() {
<button onClick={() => this.sendMessage({ message: 'Super important message', color: 'yellow' })}>
Send important Message
</button>
}
}
Result:
{
"type": "SEND_MESSAGE",
"message": "Super important message",
"color": "yellow"
}