Action features
You can add features to your actions to handle common tasks. For example, instead of writing:
class LoadText extends Action { ...
You can add checkInternet to check for internet connectivity:
class LoadText extends Action {
checkInternet = { dialog: true };
...
Or even combine multiple features:
class LoadText extends Action {
checkInternet = { dialog: true };
nonReentrant = true;
retry = { on: true };
...
Most features are turned on by setting a property in your action, like the ones above.
The optimistic features and the paged loading are different: your action extends a Kiss base
class (like OptimisticCommand or LoadPages) instead of your own base action.
All available features
| Feature | Purpose | How to add |
|---|---|---|
| checkInternet | Checks internet before the action; fails, with or without a dialog, if offline | checkInternet = { dialog: true } or { dialog: false } |
| checkInternet (abort) | Checks internet before the action; aborts silently if offline | checkInternet = { abort: true } |
| unlimitedRetryCheckInternet | Combines internet check + unlimited retry + non-reentrant | unlimitedRetryCheckInternet = true |
| nonReentrant | Aborts if the same action is already running | nonReentrant = true |
| retry | Retries the action on error with exponential backoff | retry = { on: true } |
| throttle | Limits action execution to at most once per throttle period | throttle = 5000 |
| debounce | Delays execution until after a period of inactivity | debounce = 300 |
| ignoreOld | Ignores and cancels the older actions, when a newer one is dispatched | ignoreOld = true |
| fresh | Skips the action if its data is still fresh (not stale) | fresh = 5000 |
| polling | Adds periodic polling to any action | poll and createPollingAction() |
| sequential | Runs actions one at a time, in the order they were dispatched | sequential = true |
| OptimisticCommand | Applies state changes optimistically, rolls back on error | Extend OptimisticCommand |
| OptimisticSync | Optimistic updates with coalescing; merges rapid dispatches into one sync | Extend OptimisticSync |
| OptimisticSyncWithPush | Like OptimisticSync, but with revision tracking for server pushes | Extend OptimisticSyncWithPush |
| ServerPush | Handles server-pushed updates for OptimisticSyncWithPush | Extend ServerPush |
| LoadPages | Loads a list page by page: the next, previous or first page, or all again | Extend LoadPages |
Compatibility matrix
Not all features can be combined.
Kiss throws a StoreException when you dispatch an action with incompatible features.
If you use the Kiss linter, its incompatible-action-features rule also
reports them in your editor, before you run the code.
| check Internet | non Reentrant | retry | unlimited Retry Check Internet | throttle | debounce | ignore Old | fresh | Optimistic Command | Optimistic Sync | Optimistic Sync WithPush | Server Push | Load Pages | polling | sequential | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| checkInternet | — | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ⚠️ | ✅ |
| nonReentrant | ✅ | — | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ | ✅ |
| retry | ✅ | ✅ | — | ❌ | ✅ | ❌ | ✅ | ✅ | ⚠️ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ |
| unlimitedRetryCheckInternet | ❌ | ❌ | ❌ | — | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ | ❌ | ❌ |
| throttle | ✅ | ❌ | ✅ | ❌ | — | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ | ⚠️ | ✅ |
| debounce | ✅ | ✅ | ❌ | ❌ | ✅ | — | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| ignoreOld | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | — | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| fresh | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | — | ❌ | ❌ | ❌ | ❌ | ⚠️ | ⚠️ | ✅ |
| OptimisticCommand | ✅ | ❌ | ⚠️ | ❌ | ❌ | ❌ | ❌ | ❌ | — | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| OptimisticSync | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | — | ❌ | ❌ | ❌ | ❌ | ❌ |
| OptimisticSyncWithPush | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | — | ❌ | ❌ | ❌ | ❌ |
| ServerPush | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | — | ❌ | ❌ | ❌ |
| LoadPages | ✅ | ❌ | ✅ | ⚠️ | ⚠️ | ✅ | ❌ | ⚠️ | ❌ | ❌ | ❌ | ❌ | — | ⚠️ | ✅ |
| polling | ⚠️ | ⚠️ | ❌ | ❌ | ⚠️ | ❌ | ✅ | ⚠️ | ❌ | ❌ | ❌ | ❌ | ⚠️ | — | ⚠️ |
| sequential | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ⚠️ | — |
✅ Compatible (can be combined)
❌ Incompatible (cannot be combined)
⚠️ Can be combined, but read the caveat in the feature page
Note checkInternet = { dialog: ... } and checkInternet = { abort: true } are two ways
of using the same property, so they can't be used together.
Some features also have other requirements:
retryandunlimitedRetryCheckInternetneed an async reducer. With a sync reducer, the dispatch fails with aStoreException.- Actions with
debounceorsequentialare always async, so they can't be dispatched withdispatchSync.
Clearing the features on logout
The store keeps some information for these features: the fresh keys, the throttle and
debounce locks, the ignoreOld keys, the polling timers, the sequential queues, the actions
waiting to retry,
the OptimisticSync and OptimisticSyncWithPush keys, and the revisions kept by
OptimisticSyncWithPush and ServerPush.
On logout, call store.clearInternalActionProps(), so that the actions of the previous user
stop, and don't affect the next user. For example, without it, loading the data of the new
user could be aborted because the data of the previous user is still "fresh".
class Logout extends Action {
reduce() {
this.store.clearInternalActionProps();
return State.initialState();
}
}
It does the following:
- Removes the fresh keys and the throttle locks.
- Makes the debounced actions that are still waiting finish, without running their reducer.
- Forgets the
ignoreOldkeys. The actions dispatched after it don't make the ones dispatched before it old. - Stops all polling.
- Discards the actions waiting in sequential queues, so they don't run after the logout.
- Stops the actions that retry (with
retryorunlimitedRetryCheckInternet), so they don't keep retrying for the previous user. They are aborted, so they don't fail, and don't show errors. - Releases the
OptimisticSyncandOptimisticSyncWithPushkeys. An action whose request is in flight stops when the request finishes, without sending follow-up requests. - Removes the revisions kept by
OptimisticSyncWithPushandServerPush. The server revisions you saved in the state are kept, and still used.
Actions that are already running still finish, and may still change the state.
The nonReentrant keys are not cleared directly, since they belong to the actions that are
running, but stopping a retrying action releases its key.
It's also called when the store is shut down with store.setShutDown(true).
Note it doesn't touch the app's own timers and listeners, kept in the
store props. To dispose those on logout, use
store.logOut({ disposeProps: true }). To end the store, when the app finishes or at the end
of each test, call store.dispose(),
which clears the internal action props and disposes the store props.
All features are explained in detail in the following pages: