SETTING UP YOUR COMPONENT TREE
By mapping our Redux store to a Vuex module, we are able to take advantage of Vuex's outstanding integration with your Vue components.
INJECTING YOUR VUEX STORE (which contains your Redux Module)
When using Vuex, Vue allows us to provide the store option to the root instance. Vue then injects the store into all children components and will be available within them as this.$store
.
In the snippet below, you can see us initializing our root component new Vue({...
and passing in our store
.
USING YOUR REDUX ACTION CREATORS
import 'babel-polyfill';
import Vue from 'vue';
import store from './store/vuex';
import App from './components/app.vue';
import * as actionCreators from './actions/reduxactions';
export default new Vue({
name: 'app',
store,
el: '#app',
data: {
reduxActions: actionCreators,
},
render: createElement => createElement(App),
});
As you can see in the code snippet above, we are also importing our Redux Action Creators within our root Vue instance's data
field.
These action creators would then be accessible in all children components at this.$root.reduxActions
methods: {
addTodo (e) {
var text = e.target.value
if (text.trim()) {
this.$store.dispatch(this.$root.reduxActions.addTodo(text))
}
e.target.value = ''
}
},
USING REDUX THUNKS
*If you are not already tied to Redux Thunk we recommend you use Vuex Actions to implement your asynchronous state changes.
Most large scale Redux applications need to make asynchronous state changes or state changes that rely on network requests. The standard way to make these asynchronous state changes is to use the Redux Thunk middleware.
Thunks are used to delay the dispatch of an action, or to dispatch only if a certain condition is met.
We have rewritten the native Vuex.dispatch() function to be able to properly process your existing thunks.
Below is an example of a Redux Thunk. The inner function receives the store methods dispatch
and getState
as parameters.
export function addingTodo (text) {
return (dispatch, getState) => {
// the following line is always an async ajax call, like:
// return fetch().then().then(data => dispatch(addTodo(data)))
// here we use setTimeout to fake one
setTimeout(() => {
dispatch(addTodo(text))
}, 500)
}
}
Utilizing Vuex's Mapping Features
In this section we will be focusing on Vuex's built-in helper functions for making your Redux State and Actions easy to access within your HTML templating.
mapState
When a component needs to make use of multiple store state properties or getters, declaring all these computed properties can get repetitive and verbose. To deal with this we can make use of the
mapState
helper which generates computed getter functions for us and help us save some keystrokes. Vuex Docs
Below you can see two ways of retrieving the computed property todos
. First long-hand and then with the helper function.
import { mapState } from 'vuex'
export default {
components: { Todo },
name: "Todo-List",
data () { },
computed: {
todos () {
return this.$store.state.redux.todos
}
},
}
//// VS ////
export default {
components: { Todo },
name: "Todo-List",
data () { },
computed: mapState({
todos: state => redux.todos,
},
}
By utilizing either of the above methods, we are able to reference todos
from within our HTML templating. In the below example we are creating todo components by looping over our computed todos
.
<ul class="todo-list">
<li v-for="todo in todos" :todo="todo"></todo>
</ul>
mapActions
mapActions is a Vuex's helper function that we may utilize in order to map our Redux actions within our Vuex module to component methods.
In this example, we are binding toggleAll
method to our COMPLETE_ALL
action type and clearComplete method to CLEAR_COMPLETED
action type.
import { mapActions } from 'vuex'
methods: {
// your pre-existing methods ,
...mapActions({
toggleAll: 'COMPLETE_ALL', // this.toggleAll will invoke this.$store.dispatch("COMPLETE_ALL")
clearCompleted: 'CLEAR_COMPLETED' . // this.clearCompleted will invoke this.$store.dispatch("CLEAR_COMPLETED")
})
},
By utilizing mapActions we are easily able to invoke our actions from within our HTML template:
<input @change="toggleAll({ done: !allChecked })">
<button @click="clearCompleted">