// app.ts
import { connectTo } from 'aurelia-store';
import { State } from './state';
@connectTo()
export class App {
state: State;
}
Explanation:
import { connectTo } from 'aurelia-store';
: Imports theconnectTo
decorator.@connectTo()
: This decorator automatically connects the component to the store. It creates astate
property on the component and assigns the latest state to it whenever a new state is emitted. The decorator overrides the component'sbind
andunbind
lifecycle hooks to manage the subscription to the store's state. It will also make a_stateSubscription
property available on your component where the subscription is kept and which is used during theunbind
for cleanup.
You can provide a custom selector function to connectTo
if you only want to subscribe to a specific part of the state:
// app.ts
import { connectTo } from 'aurelia-store';
import { State } from './state';
import { pluck } from 'rxjs/operators';
@connectTo({
selector: (store) => store.state.pipe(pluck('frameworks'))
})
export class App {
state: string[]; // state will now only contain the frameworks array
}
Explanation:
selector: (store) => store.state.pipe(pluck('frameworks'))
: This selector function uses the RxJSpluck
operator to extract only theframeworks
property from the state.state: string[];
: Thestate
property will now only contain theframeworks
array, not the entire state object.
You can also use multiple selectors to subscribe to different parts of the state and assign them to different properties:
// app.ts
import { connectTo } from 'aurelia-store';
import { State } from './state';
import { pluck } from 'rxjs/operators';
@connectTo({
selector: {
frameworks: (store) => store.state.pipe(pluck('frameworks')),
isLoading: (store) => store.state.pipe(pluck('isLoading'))
}
})
export class App {
frameworks: string[];
isLoading: boolean;
}
Explanation:
selector: { ... }
: An object containing multiple selector functions.frameworks: (store) => ...
: Selects theframeworks
property and assigns it to theframeworks
property on the component.isLoading: (store) => ...
: Selects theisLoading
property and assigns it to theisLoading
property on the component.
You can also specify a custom target property:
@connectTo({
target: 'appState',
selector: {
frameworks: (store) => store.state.pipe(pluck('frameworks')),
isLoading: (store) => store.state.pipe(pluck('isLoading'))
}
})
export class App {
appState: {
frameworks: string[];
isLoading: boolean;
}
}
When using target
with multiple selectors, the appState
property would contain an object with frameworks
and isLoading
properties.
You can customize the lifecycle methods used for setup and teardown:
@connectTo({
selector: (store) => store.state.pipe(pluck('frameworks')),
setup: 'attached',
teardown: 'detached'
})
export class App {
// ...
}
Explanation:
setup: 'attached'
: The subscription will be created in theattached
lifecycle method.teardown: 'detached'
: The subscription will be disposed of in thedetached
lifecycle method.
The connectTo
decorator provides several ways to handle state changes:
stateChanged(newState, oldState)
: This method is called automatically when the state changes. It receives the new state and the old state as arguments.
@connectTo()
export class App {
state: State;
stateChanged(newState: State, oldState: State) {
console.log('State changed from', oldState, 'to', newState);
}
}
targetChanged(newState, oldState)
: If you specify atarget
property, this method will be called instead ofstateChanged
.
@connectTo({
target: 'appState'
})
export class App {
appState: State;
appStateChanged(newState: State, oldState: State) {
console.log('appState changed from', oldState, 'to', newState);
}
}
onChanged: 'methodName'
: You can specify a custom method to be called when the state changes.
@connectTo({
onChanged: 'myCustomChangeHandler'
})
export class App {
state: State;
myCustomChangeHandler(newState: State, oldState: State) {
console.log('State changed in my custom handler', newState, oldState);
}
}
propertyChanged(propName, newState, oldState)
: Called after any other change handler. Receives the changed property name (or 'state' for the whole state object), the new state and the old state.
@connectTo()
export class App {
state: State;
propertyChanged(propName: string, newState: State, oldState: State) {
console.log(`Property ${propName} changed from`, oldState, 'to', newState);
}
}
Note: The change handler methods are called before the target property is updated. This allows you to compare the new and old states and potentially make further changes.