I want to use window.localStorage in Vuex in Nuxt.js
Asked Answered
B

5

4

I developing nuxt.js app. And point is login & logout.


We will develop a login to the JWT system.

You must remain logged in at vuex.

However, when I refresh the page, vuex is initialized.

I've read git vuex-persistedstate , but it's hard to understand just how to initialize and set it.

What is the best way to develop a login system in nuxt.js?

Thanks.

Bagley answered 23/5, 2017 at 5:30 Comment(4)
You can not use window.localStorage in vuex. There is no hope for me here.Bagley
What is the problem you are facing intializing vuex-persisted state. I can help you with it.Funny
@user7814783 first, My purpose is to implement the login function in nuxt.js. Vuex wants to manage login status. I want to manage it from cookies in the jwt way. However, when a page refresh occurs, vuex is initialized and can not remain logged in. Is there an easy way to do this?Bagley
i have added a descriptive answer on how to setup and use vuex-persisted state, have a look. Any doubts just commentFunny
F
16

Using vuex-persisted state would be the best use case for your scenario.

I will walk you through the process of using vuex-persisted state.

  1. Open command line, cd to your project directory, then enter npm install --save vuex-persistedstate. This will install vuex-persistedstate into your project dependencoes.
  2. Now in your store.js file or wherever your defined your vuex store, add the vuex-persistedstate plugin
import createPersistedState from "vuex-persistedstate";
import * as Cookie from "js-cookie";

Vue.use(Vuex);

export const store = new Vuex.Store({
  state: {
    user: {
      name: "john doe",
      age: " 16",
    },
    loggedIn: false,
    hobbies: ["eating", "partying"],
  },
  plugins: [
    createPersistedState({
      paths: ["user", "loggedIn"],
      getState: (key) => Cookie.getJSON(key),
      setState: (key, state) =>
        Cookie.set(key, state, { expires: 1, secure: false }),
    }),
  ],
});

  1. You also need js-cookie package which makes handling cookies easier. Use npm install --save js-cookie.
  2. The paths property says which parts of the state to persist, in our case save as cookies.If no path property is given, then the whole state is persisted
  3. From the above example we have mentioned the paths paths: ['user', 'loggedIn'], so only user and loggedIn properties of the state are saved in cookies not hobbies.
  4. In case you are using modules in your store, the way of defining the pats to persist would be as follows:
import createPersistedState from "vuex-persistedstate";
import * as Cookie from "js-cookie";

import myModule from "./myModule";
import myAnotherModule from "./myAnotherModule";

Vue.use(Vuex);

export const store = new Vuex.Store({
  state: {
    user: {
      name: "john doe",
      age: " 16",
    },
    loggedIn: false,
    hobbies: ["eating", "partying"],
  },
  modules: {
    myModule,
    myAnotherModule,
  },
  plugins: [
    createPersistedState({
      paths: ["user", "loggedIn", "myModule.<nameOfThePropretyInState>"],
      getState: (key) => Cookie.getJSON(key),
      setState: (key, state) =>
        Cookie.set(key, state, { expires: 1, secure: false }),
    }),
  ],
});
  1. In your paths you will refer to the module's property in the state you want to persist. In the above example, the property of the state that you mention of myModule is persisted. myAnotherModule state is not saved since it is not mentioned in the paths.

  2. That's it . If you want to customize the way you use vuex-persisted state and js-cookie, have a look at their documentation.

  3. If you want to check whether your desired state is saved in cookies then you can console log your cookies like this: console.log(document.cookie in your App.vue created() lifecycle hook

Funny answered 23/5, 2017 at 15:5 Comment(5)
oh... thanks. but, I am still not enough. I started the project with nuxt / koa. What is the best way to develop a login system here?Bagley
In your response, I start the project with nuxt / koa. Create an index.js file in the store folder. I have applied your code. How can I check the contents stored in cookies afterwards? Document.cookie is invalid.Bagley
Do you know of any way to get this working with Nuxt specifically? I get a "window is not defined error" because of SSR.Ternopol
I have the same issue @MichaelGiovanniPumo. Did you ever solve this?Forborne
@JonasLomholdt according to the docs of the library, if you call your plugin as /plugins/persistedState.client.js it would only be called on the client side. I'm using localstorage so that makes sense, if you are using cookies then check the docs, they have an example for cookies and nuxt tooBrunk
O
4

I have used vuex-persist package instead, very easy to get it up and running. This works for SSR too.

import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersist from 'vuex-persist'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'

Vue.use(Vuex)
let vuexLocalStorage = null;

if (process.browser) {

    vuexLocalStorage = new VuexPersist({
      key: 'vuex', // The key to store the state on in the storage provider.
      storage: window.localStorage, // or window.sessionStorage or localForage
    })
}

export function createStore() {
    return new Vuex.Store({
        state: {
        
        },
        actions,
        mutations,
        getters,
        plugins: process.browser ? [vuexLocalStorage.plugin] : []
    })
}

Just make sure to condition everything to just run in the browser

Orourke answered 30/11, 2017 at 13:26 Comment(0)
E
2

Better to use cookies for saving authorization token, look at this nuxt module

https://github.com/microcipcip/cookie-universal/tree/master/packages/cookie-universal-nuxt

Here sample on vuex store module to set cookie

//call async ajax request to get UUID
const uuidReq = await dispatch('getUUID')

if (uuidReq.hasOwnProperty('meta')) {
  commit('setState', {
    uuid: uuidReq.meta.links.me.meta.id,
    isLogin: true
  })

  // calculate expires
  const expDate = new Date()
  expDate.setTime(expDate.getTime() + (state.accExpKey - 0.3) * 1000)
  const expDate2 = new Date()
  expDate2.setTime(expDate.getTime() + 2592000 * 1000)

  const options = {
    path: '/',
    expires: expDate
  }
  const options2 = {
    path: '/',
    expires: expDate2
  }

  const cookieList = [{
      name: 'g_isLogin',
      value: true,
      opts: options2
    },
    {
      name: 'g_accKey',
      value: state.accKey,
      opts: options
    },
    {
      name: 'g_refKey',
      value: state.refKey,
      opts: options2
    },
    {
      name: 'g_userUUID',
      value: uuidReq.meta.links.me.meta.id,
      opts: options
    }
  ]
  this.$cookies.setAll(cookieList)
}

Here sample implementation on custom Nuxt middleware check existing cookie then inject them into vuex state

export default function({ store, route, redirect, app }) {
  const isLogin = app.$cookies.get('g_isLogin') === 'true'
  const accKey = app.$cookies.get('g_accKey') || ''
  const refKey = app.$cookies.get('g_refKey') || ''
  const userUUID = app.$cookies.get('g_userUUID') || ''

  // console.warn('authenticated isLogin:', isLogin)

  // If the user authenticated
  if (isLogin) {
    store.commit('user/setState', {
      isLogin: isLogin,
      accKey: accKey,
      refKey: refKey,
      uuid: userUUID
    })
  } else {
    return redirect('/?prevURL=' + route.path)
  }
}
Earn answered 2/3, 2019 at 11:26 Comment(0)
L
0

I would strongly recommend using cookies over localStorage with nuxt and the vuex store. Using a package such as univeral-cookie and the built-in nuxtServerInit action, you can populate both client and server stores by reading the cookies on the initial request from the server. You may be limited in the amount of data you can store with cookies but if you implement a RESTful-like API and store ids in your cookies whenever possible, you can server-side fetch that data to populate the full stack store thereby setting yourself up very well in cases where the user refreshes the page. I found it very handy with auth tokens, too, which expire on their own cookie-related behavior and hence wont exist in the store (or its mutation handled decoded data) in cases where the page refreshes.

Lankton answered 21/1, 2018 at 22:53 Comment(0)
C
0

for using vuex-persistedstate in nuxt both client and server , follow these steps.

For example consider you have a Vuex Module user and you want to persist it . even if you refresh or route to another page.

const user = {
    namespaced: true,
    state: () => ({
        name: 'geeekfa'
    }),
    mutations: {
        name(state, name) {
            state.name = name;
        },
    },
    getters: {
        name: (state) => {
            return state.name;
        },
    }
}
export default user
  1. install vuex-persistedstate

npm install --save vuex-persistedstate

  1. install cookie & js-cookie

npm install --save cookie js-cookie

after that your package.json is like :

  "dependencies": {
    ...
    "cookie": "^0.3.1",
    "js-cookie": "^2.2.1",
    "vuex-persistedstate": "^4.0.0-beta.3",
    ...
  }
  1. create persistedState.js in ~/plugin/persistedState.js
// persistedState.js
import createPersistedState from 'vuex-persistedstate'
import * as Cookies from 'js-cookie'
import cookie from 'cookie'

export default ({ store, req }) => {
  createPersistedState({
    paths: ['user'], // your vuex module name
    storage: {

      getItem: (key) => {
        if (process.server) {
          const parsedCookies = cookie.parse(req.headers.cookie)
          return parsedCookies[key]
        } else {
          return Cookies.get(key)
        }
      },
   
      setItem: (key, value) =>
        Cookies.set(key, value, { expires: 365, secure: false }),
      removeItem: key => Cookies.remove(key)
    }
  })(store)
}
  1. add this plugin to nuxt.config.js
plugins: [
    ...
    { src: '~/plugins/persistedState.js' }
    ...
  ],

this is enough ! you can persist user module even after refresh in both client and server side . there is no need to change ~/store/index.js file

Convulsant answered 14/3, 2021 at 13:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.