Store directory
The store directory contains your Vuex Store files. The Vuex Store comes with Nuxt out of the box but is disabled by default. Creating an index.js file in this directory enables the store.
Using a store to manage the state is important for every big application. That's why Nuxt implements Vuex in its core.
Activate the Store
Nuxt will look for the store directory. If it contains a file, that isn't a hidden file or a README.md file, then the store will be activated. This means that Nuxt will:
- Import Vuex,
-
Add the
storeoption to the root Vue instance.
Modules
Every .js file inside the store directory is transformed as a namespaced module (index being the root module). Your state value should always be a function to avoid unwanted shared state on the server side.
To get started, export the state as a function, and the getters, mutations and actions as objects.
export const state = () => ({
counter: 0
})
export const getters = {
getCounter(state) {
return state.counter
}
}
export const mutations = {
increment(state) {
state.counter++
}
}
export const actions = {
async fetchCounter({ state }) {
// make request
const res = { data: 10 };
state.counter = res.data;
return res.data;
}
}
Then, you can have a store/todos.js file:
export const state = () => ({
list: []
})
export const mutations = {
add(state, text) {
state.list.push({
text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, todo) {
todo.done = !todo.done
}
}
The store will be created as such:
new Vuex.Store({
state: () => ({
counter: 0
}),
mutations: {
increment(state) {
state.counter++
}
},
modules: {
todos: {
namespaced: true,
state: () => ({
list: []
}),
mutations: {
add(state, { text }) {
state.list.push({
text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, { todo }) {
todo.done = !todo.done
}
}
}
}
})
And in your pages/todos.vue, using the todos module:
<template>
<ul>
<li v-for="todo in todos" :key="todo.text">
<input :checked="todo.done" @change="toggle(todo)" type="checkbox">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</li>
<li><input @keyup.enter="addTodo" placeholder="What needs to be done?"></li>
</ul>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
computed: {
todos () {
return this.$store.state.todos.list
}
},
methods: {
addTodo (e) {
this.$store.commit('todos/add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'todos/toggle'
})
}
}
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
The module method also works for top-level definitions without implementing a sub-directory in the store directory.
Example for state: you create a file store/state.js and add the following.
export default () => ({
counter: 0
})
And the corresponding getters can be in the file store/getter.js
export default {
getCounter(state) {
return state.counter
}
}
And the corresponding mutations can be in the file store/mutations.js
export default {
increment(state) {
state.counter++
}
}
And the corresponding actions can be in the file store/actions.js
export default {
async fetchCounter({ state }) {
// make request
const res = { data: 10 };
state.counter = res.data;
return res.data;
}
}
Example folder structure
A complex store setup file/folder structure might look like this:
store/
--| index.js
--| ui.js
--| shop/
----| cart/
------| actions.js
------| getters.js
------| mutations.js
------| state.js
----| products/
------| mutations.js
------| state.js
------| itemsGroup1/
--------| state.js
Plugins in the Store
You can add additional plugins to the store by putting them into the store/index.js file:
import myPlugin from 'myPlugin'
export const plugins = [myPlugin]
export const state = () => ({
counter: 0
})
export const mutations = {
increment(state) {
state.counter++
}
}
More information about the plugins: Vuex documentation .
The nuxtServerInit Action
If the action nuxtServerInit is defined in the store and the mode is universal, Nuxt will call it with the context (only from the server-side). It's useful when we have some data on the server we want to give directly to the client-side.
For example, let's say we have sessions on the server-side and we can access the connected user through req.session.user. To add the authenticated user to our store, we update our store/index.js to the following:
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}
store/index.js) will receive this action. You'll need to chain your module actions from there.The context is given to nuxtServerInit as the 2nd argument in the asyncData method.
If nuxt generate is ran, nuxtServerInit will be executed for every dynamic route generated.
nuxtServerInit actions must return a Promise or leverage async/await to allow the nuxt server to wait on them.actions: {
async nuxtServerInit({ dispatch }) {
await dispatch('core/load')
}
}
Vuex Strict Mode
Strict mode is enabled by default on dev mode and turned off in production mode. To disable strict mode in dev, follow the below example in store/index.js:
export const strict = false
Clément Ollivier
Daniel Roe
Alex Hirzel
Ajeet Chaulagain
René Eschke
Sébastien Chopin
Nico Devs
Muhammad
Nazaré da Piedade
Naoki Hamada
Tom
Yann Aufray
Anthony Chu
Nuzhat Minhaz
Lucas Portet
Richard Schloss
Xanzhu
bpy
Antony Konstantinidis
Hibariya
Jose Seabra
Eze
Florian LEFEBVRE
Lucas
Julien SEIXAS
Hugo
Sylvain Marroufin
Spencer Cooley
Piotr Zatorski
Vladimir Semenov
Harry Allen
kazuya kawaguchi
Unai Mengual
Hyunseung Lee
Alexandre Chopin
pooya parsa
Nick Medrano
Mosaab Emam
Iljs Путлер Капут
Heitor Ramon Ribeiro
Nero
Yoon Han
Ikko Ashimine
FamCodings
Ayouli
F. Hinkelmann
felipesuri
Christophe Carvalho Vilas-Boas
Leoš Literák
Trizotti
Marcello Bachechi
Rodolphe
Thomas Underwood
Shek Evgeniy
Lukasz Formela
Hugo Torzuoli