championswimmer / vuex-persist

A Vuex plugin to persist the store. (Fully Typescript enabled)
http://championswimmer.in/vuex-persist
MIT License
1.67k stars 116 forks source link

[Nuxt] Value is not restored, but available in storage #119

Open MateuszG opened 5 years ago

MateuszG commented 5 years ago

Create nuxt project and add vuex-presist

store/index.js

import Vue from 'vue';

export const state = () => ({
    preview: {},
    templateR: false
})

export const mutations = {
    update(state, data) {
        console.log(state)
        for (let field of Object.keys(data)) {
            Vue.set(state, field, data[field]);
        }
    },
}
export const getters = {
}

nuxt.config.js

export default {
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: process.env.npm_package_name || '',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{ src: '~/plugins/vuex-persist', ssr: false },
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://bootstrap-vue.js.org/docs/
'bootstrap-vue/nuxt',
],
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
}
}
}

package.json

{
  "name": "vuetest",
  "version": "1.0.0",
  "description": "My sublime Nuxt.js project",
  "author": "Mateusz",
  "private": true,
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate"
  },
  "dependencies": {
    "bootstrap": "^4.1.3",
    "bootstrap-vue": "^2.0.0-rc.11",
    "nuxt": "^2.0.0",
    "vuex-persist": "^2.0.1"
  },
  "devDependencies": {
    "nodemon": "^1.18.9"
  }
}

and finally:


<div class="container">



Uncomment `this.$store.commit('update', {preview: 1})` only to save value (which works), comment this line and then restart app an, value will not be loaded, why?
itsfarseen commented 5 years ago

I noticed a similar problem.

This won't redirect:

  created: function () {
    if (this.$store.state.isLoggedIn) {
      this.$router.replace('/admin/Dashboard')
    }
  },

While this does:

  created: function () {
    if (this.$store.state.isLoggedIn) {
      this.$router.replace('/admin/Dashboard')
    }
    if (this.$store.state.isLoggedIn) {
      this.$router.replace('/admin/Dashboard')
    }
  },

So does this:

  created: function () {
    console.log(this.$store.state.isLoggedIn)
    if (this.$store.state.isLoggedIn) {
      this.$router.replace('/admin/Dashboard')
    }
  },
itsfarseen commented 5 years ago

Is this a race condition?

itsfarseen commented 5 years ago

I removed window.onNuxtReady in plugins/vuex-persist.js:

export default ({ store }) => {
  new VuexPersistence({
    key: 'key'
  }).plugin(store)
}

Now it appears to work.

michael-trinity commented 4 years ago

I removed window.onNuxtReady in plugins/vuex-persist.js:

export default ({ store }) => {
  new VuexPersistence({
    key: 'key'
  }).plugin(store)
}

Now it appears to work.

you're a lifesaver, been struggling for 6 hours on why it kept losing my states.

nwittwer commented 4 years ago

This fix https://github.com/championswimmer/vuex-persist/issues/119#issuecomment-504863193 seems to work for Nuxt apps with ssr: false (previously called: mode: 'spa').

However it doesn't seem to work for ssr: true (previously called mode: 'universal'). The window.onNuxtReady seems to be important for SSR apps; not having it leads to errors about the DOM being out of sync.

Docs about the ssr property: https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-ssr

Saunved commented 4 years ago

Along with removing window.onNuxtReadyI had to explicitly specify the storage for it to start working:

export default ({ store }) => {
  new VuexPersistence({
    key: 'key',
    storage: window.localStorage
  }).plugin(store)
}
IvoPereira commented 3 years ago

This fix #119 (comment) seems to work for Nuxt apps in SPA mode.

However it doesn't seem to work for Universal mode. The window.onNuxtReady seems to be important for Universal SSR apps; not having it leads to errors about the DOM being out of sync.

I have noticed this as well.

At the moment this is what I have got working:

import VuexPersistence from 'vuex-persist'

export default ({ store }) => {
  new VuexPersistence({
    key: 'state',
    storage: window.localStorage,
  }).plugin(store)
}

This is the only way I was able to store and correctly have restored data back in components.

Apart of this, I needed to use localStorage, as when using localForage it didn't work.

Having it this way, does correctly store/restore the state, while using localForage instead doesn't.

However, as you correctly say, using this without window.onNuxtReady does produce a client-side rendered virtual DOM tree is not matching server-rendered content message (while having window.onNuxtReady didn't but didn't correctly restore the state as well).

What is the recommended way to setup this for Universal SSR apps?

abelant commented 2 years ago
import { VuexPersistence } from 'vuex-persist'

export default ({ store }) => {
  new VuexPersistence({
    reducer: state => ({
      auth: {
        user: state.auth.user
      },
      userInteraction: {
        userInteractions: state.userInteraction.userInteractions,
      },
    })
  }).plugin(store)
}

This solved my issue by saving state instances to vuex persist plugin. Hope it helps 👍🏼