État de Vuex lors de l'actualisation de la page

106

Mon application utilise l'API Firebase pour l'authentification des utilisateurs, en enregistrant l'état de connexion sous forme de valeur booléenne dans un état Vuex.

Lorsque l'utilisateur se connecte, je règle l' état de connexion et j'affiche conditionnellement le bouton Connexion / Déconnexion en conséquence.

Mais lorsque la page est actualisée, l'état de l'application vue est perdu et réinitialisé par défaut

Cela pose un problème car même lorsque l'utilisateur est connecté et que la page est actualisée, l' état de connexion est remis à false et le bouton de connexion est affiché à la place du bouton de déconnexion même si l'utilisateur reste connecté ...

Que dois-je faire pour éviter ce comportement

Dois-je utiliser des cookies Ou toute autre meilleure solution est disponible ...

    -
boomboxboy
la source
2
J'utilise n'importe quel type de stockage local pour gérer cela. Cela peut être des cookies ou autre chose
Hammerbot
@El_Matella en dehors des cookies quelle autre méthode utilisez-vous pour stocker des données localement
boomboxboy
1
En général, j'utilise un package npm de stockage local qui peut choisir la meilleure méthode pour stocker des données pour moi: npmjs.com/package/local-storage "L'API est un moyen simplifié d'interagir avec tout ce qui est localStorage. Notez que lorsque localStorage est non pris en charge dans le navigateur actuel, une solution de secours vers un stockage en mémoire est utilisée de manière transparente. "
Hammerbot
@El_Matella merci beaucoup ... je vais jeter un oeil
boomboxboy

Réponses:

110

Il s'agit d'un cas d'utilisation connu. Il existe différentes solutions.

Par exemple, on peut utiliser vuex-persistedstate. Il s'agit d'un plugin pour vuexgérer et stocker l'état entre les actualisations de la page.

Exemple de code:

import { Store } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import * as Cookies from 'js-cookie'

const store = new Store({
  // ...
  plugins: [
    createPersistedState({
      getState: (key) => Cookies.getJSON(key),
      setState: (key, state) => Cookies.set(key, state, { expires: 3, secure: true })
    })
  ]
})

Ce que nous faisons ici est simple:

  1. vous devez installer js-cookie
  2. sur getStatenous essayons de charger un état sauvéCookies
  3. sur setStatenous sauvons notre état pourCookies

Documents et instructions d'installation: https://www.npmjs.com/package/vuex-persistedstate

sobolevn
la source
Merci ... Je viens de regarder la page github du plugin ... Merci encore
boomboxboy
8
Avez-vous besoin de faire quelque chose de spécifique pour définir / obtenir les données? Lors du rechargement, mes données sont réinitialisées par défaut. Juste en définissant via ceci. $ Store.state.user, des objets essayés et des chaînes simples - pas de chance.
DogCoffee
6
Parce que les cookies sont transmis entre le client et le serveur, je regarderais probablement plutôt le stockage local ...
James Westgate
comment enregistrer l'état de aws-amplify? car il est trop gros pour contenir des cookies et le stockage local ne fonctionnera pas en mode privé safari
traqué le
@hounded je suis également confronté au même problème, trouvé une solution à cela?
Adil
54

Lors de la création de votre état VueX, enregistrez-le dans le stockage de session à l'aide du plugin vuex-persistedstate . De cette manière, les informations seront perdues lors de la fermeture du navigateur. Évitez d'utiliser des cookies car ces valeurs circuleront entre le client et le serveur.

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

Vue.use(Vuex);

export default new Vuex.Store({
    plugins: [createPersistedState({
        storage: window.sessionStorage,
    })],
    state: {
        //....
    }
});

À utiliser sessionStorage.clear();lorsque l'utilisateur se déconnecte manuellement.

James Westgate
la source
13
Je suis surpris que la solution cookies obtienne autant d'étoiles. Je pense que cette solution est bien meilleure car elle efface automatiquement tous les états lorsque la fenêtre du navigateur est fermée. Je n'aime pas envoyer mes données d'état sous forme de cookies au serveur, et je ne veux pas non plus conserver les données sensibles lorsque la fenêtre du navigateur se ferme.
Mark Hagers le
Vous êtes également limité à 8k au total avec vos en-têtes, y compris les cookies.
James Westgate le
2
@MarkHagers et il est supporté nativement depuis IE8! Pas besoin de charger du code supplémentaire.
Fabian von Ellerts le
1
J'obtenais une erreur vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
Akin Hwan
1
@Akin - L'erreur suggère que vous avez une référence circulaire dans votre état, un objet référence un autre objet qui renvoie finalement au premier objet.
James Westgate
11

L'état Vuex est conservé en mémoire. Le chargement de la page purgera cet état actuel. C'est pourquoi l'état ne persiste pas lors du rechargement.

Mais le vuex-persistedstateplugin résout ce problème

npm install --save vuex-persistedstate

Importez maintenant ceci dans le magasin.

import Vue from 'vue'
import Vuex from 'vuex'
import account from './modules/account'
import createPersistedState from "vuex-persistedstate";

Vue.use(Vuex);

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

Cela fonctionnait parfaitement avec une seule ligne de code: plugins: [createPersistedState()]

Rijo
la source
10

Je pense que l'utilisation de cookies / localStorage pour enregistrer l'état de connexion peut provoquer une erreur dans certaines situations.
Firebase enregistre déjà les informations de connexion sur localStorage pour nous, notamment expirationTime et refreshToken.
Par conséquent, j'utiliserai le hook créé par Vue et l'API Firebase pour vérifier l'état de connexion.
Si le jeton a expiré, l'API actualisera le jeton pour nous.
Nous pouvons donc nous assurer que l'affichage de l'état de connexion dans notre application est égal à Firebase.

new Vue({
    el: '#app',
    created() {
        firebase.auth().onAuthStateChanged((user) => {
            if (user) {
                log('User is logined');
                // update data or vuex state
            } else {
                log('User is not logged in.');
            }
        });
    },
});
Andrew - oahehc
la source
la meilleure approche officielle et recommandée contre cette situation
alijunior
8

mettre en état:

producer: JSON.parse(localStorage.getItem('producer') || "{}")

mettre sur les mutations:

localStorage.setItem("producer",JSON.stringify(state.producer)) // OR
localStorage.removeItem("producers");

fonctionne bien pour moi!

Léonard Filipe
la source
1

J'ai résolu ce problème en réinitialisant mes en-têtes à chaque fois que je recharge également les données utilisateur, je ne sais pas ce qui est mieux ...

new Vue({
    el: 'vue',
    render: h => h(VueBox),
    router,
    store,

    computed: {
        tokenJWT () {
            return this.$store.getters.tokenCheck
        },
    },


    created() {
        this.setAuth()

    },

    methods:
        Object.assign({}, mapActions(['setUser']), {

            setAuth(){
                if (this.tokenJWT) {
                    if (this.tokenJWT === 'expired') {
                        this.$store.dispatch('destroyAuth')
                        this.$store.dispatch('openModal')
                        this.$store.dispatch('setElModal', 'form-login')

                    } else {
                        window.axios.defaults.headers.common = {
                            'Accept': 'application/json',
                            'Authorization': 'Bearer ' + this.tokenJWT
                        }
                        axios.get( api.domain + api.authApi )
                            .then(res => {
                                if (res.status == 200) {
                                    this.setUser( res.data.user )
                                }
                            })
                            .catch( errors => {
                                console.log(errors)
                                this.destroyAuth()
                            })
                    }
                }
            }
        })

})
Alenn G'Kar
la source