Skip to content
This repository has been archived by the owner on Feb 4, 2022. It is now read-only.

Delete persisted state #88

Closed
zagreusinoz opened this issue Nov 16, 2017 · 14 comments
Closed

Delete persisted state #88

zagreusinoz opened this issue Nov 16, 2017 · 14 comments

Comments

@zagreusinoz
Copy link

zagreusinoz commented Nov 16, 2017

Do you want to request a feature or report a bug?
Feature

What is the current behavior?
There is no way to delete the persisted state programmatically, there are use cases for removing the state in local storage.

If the current behavior is a bug, please provide the steps to reproduce.

What is the expected behavior?
We should be able to remove the state from local storage either with localStorage.removeItem('vuex') or something like this.$store.clear.

If this is a feature request, what is motivation or use case for changing the behavior?

When my users log out I want to remove all of the state data, this way when a different person logs in none of the existing data is shared.

I tried to do this with localStorage.removeItem('vuex') however I see that in #37 it's commented that the plugin gets there first and the state is rewritten again.

It's possible to do it manually, however this would mean setting all of the states to default values in all of the modules as far as I can tell which is not very efficient.

@robinvdvleuten
Copy link
Owner

The recommended way here is to stay away from the localStorage entry. If you would like the remove any "user" related state, you can do that with a mutation on your state. This keeps all state related issues to a bare minimum in your application.

@TitanFighter
Copy link

TitanFighter commented Mar 31, 2018

After deep digging in internet I found a clean solution which works well.

Based on these 2 answers (#1 #2) I made a workable code.

My structure of Vuex's index.js:

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'

import { header } from './header'
import { media } from './media'

Vue.use(Vuex)

const store = new Vuex.Store({
  plugins: [createPersistedState()],

  modules: {
    header,
    media
  }
})

export default store

Inside each module we need to move all states into separated var initialState and in mutation define a function resetState, like below for media.js:

const initialState = () => ({
  stateOne: 0,

  stateTwo: {
    isImportedSelected: false,
    isImportedIndeterminate: false,

    isImportedMaximized: false,
    isImportedSortedAsc: false,

    items: [],

  stateN: ...
  }
})

export const media = {
  namespaced: true,

  state: initialState, // <<---- Our States

  getters: {
  },

  actions: {
  },

  mutations: {
    resetState (state) {
      const initial = initialState()
      Object.keys(initial).forEach(key => { state[key] = initial[key] })
    },
  }

}

In Vue component we can use it like:

<template>
</template>

<script>
  import { mapMutations } from 'vuex'

  export default {
    name: 'SomeName',

    data () {
      return {
        dataOne: '',
        dataTwo: 2
      }
    },

    computed: {
    },

    methods: {
      ...mapMutations('media', [ // <<---- define module
        'resetState' // <<---- define mutation
      ]),

      logout () {
        this.resetState() // <<---- use mutation
        // ... any code if you need to do something here
      }
    },

    mounted () {
    }
  } // End of 'default'

</script>

<style>
</style>

@AlexeyKot
Copy link

Thanks! But if I have lots of modules, do I need to call such reset methods for all of my modules inside logout() method (which is also is a method inside auth module)?

@vkatsar
Copy link

vkatsar commented Jun 27, 2019

Hello everybody,

I think its better to use the reducer method to remove all the vuex state.

createPersistedState({
    key: 'vuex',
    reducer (val) {
      if(val.user.token === null) { // val.user.token (your user token for example)
        return {}
      }
      return val
    }
  })(store)

@tcamde
Copy link

tcamde commented Nov 22, 2019

@vkatsar
I implemented your solution, thanks for that!

Just two remarks for other people trying this. In my setup I had to remove the "(store)" to make it work. Also it's important to know that the state will only be removed after a page refresh, so my logout action looks like this:

Action:

async logout ({ commit }) {    
    await AuthenticationApi.logout()  // Only in my setup: async call to server invalidate token on server-side
    commit('logout') 
    location.reload()  
  }

Mutation:

  logout: (state) => {
    state.token = null // Only in my setup remove session token
    state.isUserLoggedIn = false // this will trigger the vue-persist-store plugin to set all state to empty on the location relaod

  },

and the reducer:

createPersistedState({
              key: 'vuex',              
              reducer (val) {                                
                if(val.authentication.isUserLoggedIn === false) { // return empty state when user logged out                
                  return {}
                }
                return val
              }
            })

@kasperkamperman
Copy link

@tcamde how does you "logOutUser" look? Is this needed? It seems that the answer is not complete.

commit('logOutUser') // this will cause the vue-persist-store plugin to set all state to empty

@xlcrr
Copy link

xlcrr commented Mar 24, 2020

I was able to get this working with the reducer method and

axios.get('logout')
  .then(resp => {
       window.location.href = window.location.href;
       this.$store.commit('logout)';
   });

This thread should probably be posted on the readme

@uxinkc
Copy link

uxinkc commented May 27, 2020

Can someone please provide a full example here of how to delete the persisted state. All of the above make reference to code that isn't visible to the Reader, so there is no way to connect the dots and understand how to actually use reducer.

For example, what is val in the above reducer examples and how is that called when a User clicks a logout button? How would calling a mutation to "logout" clear the persisted data? Some context in examples goes a very long way, and a full solution with all relevant code helps even more.

@tcamde
Copy link

tcamde commented May 27, 2020

@uxinkc
@kasperkamperman

I updated my example with the full code, though it might be a bit specific to my use-case

@uxinkc
Copy link

uxinkc commented May 27, 2020

@tcamde I appreciate the update!

had a couple more questions for you...

  1. What does val represent in your example below and how is the reducer called?
reducer(val){
  if(val.authentication.isUserLoggedIn === false) ...
}
  1. Is authentication in above the name of the store module that has the isUserLoggedIn state property?

@ttntm
Copy link

ttntm commented Jun 30, 2020

Thanks @tcamde, this really helped:

reducer (val) {
  if(!val.user.currentUser) { // return empty state when user logged out
    return {}
  }
  return val
},

if(!val.user.currentUser) needs to point to the state object's key one stores the "user is logged in" token/value/... in.

In my case, state.currentUser is initialized as null in my store's user.js module. The reducer's parameter val seems to represent the whole "persisted state" as such, making it possible to access state values just like you would from inside your app with this.$store.state.moduleName.stateKeyName.

So, to answer @uxinkc's second question: yes, authentication is a store module's name and in this module there's that state property.

@ttntm ttntm mentioned this issue Jun 30, 2020
@lvsong77
Copy link

@tcamde

Sorry to bother you, but is it necessary to refresh the page to logout? I have the same problem, but 'location.reload' will lead to a while of blank white screen in front of user. Is there any better plan by now?

@KimZing
Copy link

KimZing commented Jul 16, 2021

Hello everybody,

I think its better to use the reducer method to remove all the vuex state.

createPersistedState({
    key: 'vuex',
    reducer (val) {
      if(val.user.token === null) { // val.user.token (your user token for example)
        return {}
      }
      return val
    }
  })(store)

I try the way to reset state in vuex modules when user logout, but other feature of my program not work。
so i used the following code, it works well

createPersistedState({
      key: 'any-key',
      storage: {
        setItem: (key, value) => {
          // parse value
          const state = JSON.parse(value)
          // if token not exist,clean storage
          if (state.user.token === null) {
            window.localStorage.clear()
            return
          }
          window.localStorage.setItem(key, value)
        },
        getItem: window.localStorage.getItem,
        removeItem: window.localStorage.removeItem
      }
    })

@osmelg
Copy link

osmelg commented Jan 28, 2022

@vkatsar I implemented your solution, thanks for that!

Just two remarks for other people trying this. In my setup I had to remove the "(store)" to make it work. Also it's important to know that the state will only be removed after a page refresh, so my logout action looks like this:

Action:

async logout ({ commit }) {    
    await AuthenticationApi.logout()  // Only in my setup: async call to server invalidate token on server-side
    commit('logout') 
    location.reload()  
  }

Mutation:

  logout: (state) => {
    state.token = null // Only in my setup remove session token
    state.isUserLoggedIn = false // this will trigger the vue-persist-store plugin to set all state to empty on the location relaod

  },

and the reducer:

createPersistedState({
              key: 'vuex',              
              reducer (val) {                                
                if(val.authentication.isUserLoggedIn === false) { // return empty state when user logged out                
                  return {}
                }
                return val
              }
            })

best option available out there...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests