@tixel/vuex-correlated-effects
Version:
Correlated effects is a side effect model for Vuex. Correlated effects use subscribers to provide new sources of actions such as network requests, web socket messages and time-based events. Effects can be correlated back to the component that initially di
247 lines (206 loc) • 6.57 kB
Markdown
# vuex-effects
Effects is a side effect model for Vuex. Effects use subscribers to provide new sources of actions such as network requests, web socket messages and time-based events.
- [Basic example](https://codesandbox.io/s/vuex-effects-1-92hqr)
## Fork
This repo has been forked from the original and adds some additional features:
- [Babel compilation](#building)
- [Correlated effects](#correlated-actions)
## Installation
```bash
$ npm install /vuex-correlated-effects
```
## Usage
Import Plugin
```js
import VuexEffects from "@tixel/vuex-correlated-effects";
Vue.use(VuexEffects(store));
```
Use this in component like this
```js
import { mapActions, mapState } from 'vuex';
export default {
// ...
effects: {
actions: {
getTasksList: {
after(action, state) {
localStorage.setItem('tasksList', JSON.stringify(this.tasksList));
}
}
}
},
// ...
computed: {
...mapState(['tasksList']),
},
mounted() {
this.getTasksList();
},
methods: {
...mapActions(['getTasksList']),
},
};
```
Use this outside component (global effects) like this
```js
// @/src/store/tasksEffects.js
export default {
effects: {
actions: {
getTasksList: {
after(action, state) {
localStorage.setItem('tasksList', JSON.stringify(this.tasksList));
}
}
}
},
};
```
If your effects is outside component (global effects) then you must include your global effects in second parameter
```js
// main.js
// ...
import VuexEffects from "vuex-effects";
import tasksEffects from '@/store/effets/tasksEffects';
Vue.use(VuexEffects(store, [tasksEffects]));
// ...
```
## Effects Options
### Actions
By default action effects is called before action dispatched if you pass your effect like a function and receives the action descriptor and current store state as arguments.
Let's look at this example effects:
```js
effects: {
actions: {
getTasksList(action, state) {
// this code invokes BEFORE vuex action has finished
localStorage.setItem('tasksList', JSON.stringify(this.tasksList));
}
}
}
```
If you want to invoke your effects after vuex action, you must to use object notation like this
```js
effects: {
actions: {
getTasksList: {
before(action, state) {
// this code invokes BEFORE vuex action has finished
localStorage.setItem('tasksListBefore', JSON.stringify(this.tasksList));
},
after(action, state) {
// this code invokes AFTER vuex action has finished
localStorage.setItem('tasksListAfter', JSON.stringify(this.tasksList));
}
}
}
}
```
By default, new actions effects is added to the end of the chain, so it will be executed after other effects that were added before. This can be overridden by adding `prepend: true` to options, which will add the handler to the beginning of the chain.
Let's look at this example effects:
```js
effects: {
actions: {
getTasksList: {
prepend: true, // this will add your effects to the beginning of the chain
after(action, state) {
// this code invokes AFTER vuex action has finished
localStorage.setItem('tasksListAfter', JSON.stringify(this.tasksList));
}
}
}
}
```
You can also use `handler` as an alias for `before`
```js
effects: {
actions: {
getTasksList: {
prepend: true, // this will add your effects to the beginning of the chain
handler(action, state) { // same as before()
// this code invokes BEFORE vuex action has finished
localStorage.setItem('tasksListAfter', JSON.stringify(this.tasksList));
}
}
}
}
```
For using it with namespaced state
```js
effects: {
actions: {
'tasks/getTasksList': { // this is an analogy for mapActions argument
prepend: true, // this will add your effects to the beginning of the chain
handler(action, state) { // same as before()
// this code invokes BEFORE vuex action has finished
localStorage.setItem('tasksListAfter', JSON.stringify(this.tasksList));
}
}
}
}
```
#### Correlated actions
The forked repo adds additional functionality so that you can correlate dispatched actions with a particular component, let's take a look at an example:
```js
props: {
name: {
default: '',
type: String
}
},
effects: {
actions: {
'tasks/getTasksList': {
matchComponentProps: ['name'],
before() {
// do something for this named component
},
},
}
}
```
You could include the above component like this:
```html
<my-component name="uniqueName"></my-component>
```
Then to ensure that an effect runs for only this component then dispatch within another Vue component like this:
```js
this.$store.dispatch('tasks/getTasksList', { match: [{name: 'uniqueName' }] })
```
**Note**: Correlated actions do not apply for mutations.
### Mutations
Mutations effects is called after every mutation and receives the mutation descriptor and post-mutation state as arguments.
Mutations doesn't have `before` and `after` methods unlike Actions, only the `handler` method is avalable in object notation.
Let's look at this example effects:
```js
effects: {
mutations: {
setTasksList(mutation, state) {
// this code invokes AFTER vuex mutation has finished
console.log(mutation.payload)
console.log(state)
}
}
}
```
By default, new mutations effects is added to the end of the chain, so it will be executed after other mutations effects that were added before. This can be overridden by adding `prepend: true` to options, which will add the handler to the beginning of the chain.
Let's look at this example effects:
```js
effects: {
mutations: {
getTasksList: {
prepend: true, // this will add your effects to the beginning of the chain
handler(mutation, state) {
// this code invokes AFTER vuex mutation has finished
localStorage.setItem('tasksListAfter', JSON.stringify(this.tasksList));
}
}
}
}
```
## Building
If you want to make changes to the code then you can build and watch scripts are in `package.json`:
```bash
$ npm run build
$ npm run watch
```