Vuex Store

Using a store to manage the state is important to every big application, that's why nuxt.js implement vuex in its core.

Activate the Store

Nuxt.js will look for the store directory, if it exists, it will:

  1. Import Vuex
  2. Add vuex module in the vendors bundle
  3. Add the store option to the root Vue instance.

Nuxt.js lets you have 2 modes of store, choose the one you prefer:

  • Classic: store/index.js returns a store instance
  • Modules: every .js file inside the store directory is transformed as a namespaced module (index being the root module)

Classic mode

To activate the store with the classic mode, we create the store/index.js file and export the store instance:

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    counter: 0
  },
  mutations: {
    increment (state) {
      state.counter++
    }
  }
})

export default store

We don't need to install vuex since it's shipped with nuxt.js

We can now use this.$store inside our components:

<template>
  <button @click="$store.commit('increment')">{{ $store.state.counter }}</button>
</template>

Modules mode

Nuxt.js lets you have a store directory with every file corresponding to a module.

If you want this option, export the state, mutations and actions in store/index.js instead of a store instance:

export const state = {
  counter: 0
}

export const mutations = {
  increment (state) {
    state.counter++
  }
}

Then, you can have a store/todos.js file:

export const state = {
  list: []
}

export const mutations = {
  add (state, text) {
    state.list.push({
      text: text,
      done: false
    })
  },
  delete (state, { todo }) {
    state.list.splice(state.list.indexOf(todo), 1)
  },
  toggle (state, todo) {
    todo.done = !todo.done
  }
}

The store will be as such:

new Vuex.Store({
  state: { counter: 0 },
  mutations: {
    increment (state) {
      state.counter++
    }
  },
  modules: {
    todos: {
      state: {
        list: []
      },
      mutations: {
        add (state, { text }) {
          state.list.push({
            text,
            done: false
          })
        },
        delete (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">
      <input type="checkbox" :checked="todo.done" @change="toggle(todo)">
      <span :class="{ done: todo.done }">{{ todo.text }}</span>
    </li>
    <li><input placeholder="What needs to be done?" @keyup.enter="addTodo"></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>
You can also have modules by exporting a store instance, you will have to add them manually on your store.

The fetch Method

The fetch method is used to fill the store before rendering the page, it's like the data method except it doesn't set the component data.

More information about the fetch method: API Pages fetch

The nuxtServerInit Action

If the action nuxtServerInit is defined in the store, nuxt.js 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 trough req.session.user. To give 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)
    }
  }
}

If you are using the Modules mode of the Vuex store, only the primary module (in 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, it is the same as the data or fetch method except that context.redirect() and context.error() are omitted.

Caught a mistake or want to contribute to the documentation? Edit this page on GitHub!