Vuex-Status bei Seitenaktualisierung

97

Meine App verwendet die Firebase-API für die Benutzerauthentifizierung und speichert den Anmeldestatus als booleschen Wert in einem Vuex-Status.

Wenn sich der Benutzer anmeldet, setze ich den Anmeldestatus und zeige die Schaltfläche Anmelden / Abmelden entsprechend an.

Wenn die Seite aktualisiert wird, geht der Status der Vue-App verloren und wird auf die Standardeinstellungen zurückgesetzt

Dies verursacht ein Problem, da selbst wenn der Benutzer angemeldet und die Seite aktualisiert ist, der Anmeldestatus auf false zurückgesetzt wird und die Anmeldeschaltfläche anstelle der Abmeldeschaltfläche angezeigt wird, obwohl der Benutzer angemeldet bleibt.

Was soll ich tun, um dieses Verhalten zu verhindern?

Soll ich Cookies verwenden oder ist eine andere bessere Lösung verfügbar ...

    - -
Boomboxboy
quelle
1
Ich benutze jede Art von lokalem Speicher, um damit umzugehen. Das können Kekse oder etwas anderes sein
Hammerbot
@ El_Matella abgesehen von Cookies, welche andere Methode verwenden Sie, um Daten lokal zu speichern
Boomboxboy
1
Im Allgemeinen verwende ich ein lokales Speicher-npm-Paket, das die beste Methode zum Speichern von Daten für mich auswählen kann: npmjs.com/package/local-storage "Die API ist eine vereinfachte Möglichkeit, mit allen Dingen zu interagieren, die localStorage ist. Beachten Sie, dass dies bei localStorage der Fall ist Im aktuellen Browser nicht unterstützt, wird ein Fallback auf einen In-Memory-Speicher transparent verwendet. "
Hammerbot
@ El_Matella vielen Dank ... Ich werde einen Blick darauf werfen
Boomboxboy

Antworten:

95

Dies ist ein bekannter Anwendungsfall. Es gibt verschiedene Lösungen.

Zum Beispiel kann man verwenden vuex-persistedstate. Dies ist ein Plugin vuexzum Behandeln und Speichern des Status zwischen Seitenaktualisierungen.

Beispielcode:

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 })
    })
  ]
})

Was wir hier machen, ist einfach:

  1. Sie müssen installieren js-cookie
  2. am getStateversuchen wir den gespeicherten Zustand von zu ladenCookies
  3. auf setStateretten wir unseren Staat zuCookies

Dokumente und Installationsanweisungen: https://www.npmjs.com/package/vuex-persistedstate

sobolevn
quelle
Danke ... Ich habe mir gerade die Github-Seite des Plugins angesehen ... Nochmals vielen Dank
Boomboxboy
8
Müssen Sie etwas Spezielles tun, um die Daten festzulegen / abzurufen? Beim erneuten Laden werden meine Daten auf die Standardeinstellungen zurückgesetzt. Einfach über diesen. $ Store.state.user einstellen, Objekte und einfache Strings ausprobiert - kein Glück.
DogCoffee
6
Da Cookies zwischen Client und Server übertragen werden, würde ich mir wahrscheinlich stattdessen den lokalen Speicher ansehen ...
James Westgate
Wie speichere ich den Status von aws-amplify? Da es zu groß ist, um in Cookies zu passen, funktioniert localstorage im privaten Safari-Modus nicht
verfolgt
@hounded Ich stehe auch vor dem gleichen Problem, habe ich eine Lösung dafür gefunden?
Adil
40

Speichern Sie Ihren VueX-Status beim Erstellen im Sitzungsspeicher mit dem Plugin vuex-persistedstate . Auf diese Weise gehen die Informationen verloren, wenn der Browser geschlossen wird. Vermeiden Sie die Verwendung von Cookies, da diese Werte zwischen Client und Server übertragen werden.

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: {
        //....
    }
});

Verwenden Sie diese sessionStorage.clear();Option, wenn sich der Benutzer manuell abmeldet.

James Westgate
quelle
11
Ich bin überrascht, dass die Cookies-Lösung so viele Sterne bekommt. Ich denke, diese Lösung ist viel besser, da sie automatisch alle Zustände löscht, wenn das Browserfenster geschlossen wird. Ich mag es nicht, meine Statusdaten als Cookies an den Server zu senden, und ich möchte auch keine sensiblen Daten beibehalten, wenn das Browserfenster geschlossen wird.
Mark Hagers
Sie sind auch auf insgesamt 8.000 mit Ihren Headern einschließlich Cookies beschränkt.
James Westgate
2
@ MarkHagers und es wird seit IE8 nativ unterstützt! Es muss kein zusätzlicher Code geladen werden.
Fabian von Ellerts
Ich habe eine Fehlermeldung erhalten vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
Akin Hwan
1
@Akin - Der Fehler deutet darauf hin, dass Sie einen Zirkelverweis in Ihrem Status haben. Ein Objekt verweist auf ein anderes Objekt, das schließlich auf das erste Objekt verweist.
James Westgate
9

Ich denke, die Verwendung von Cookies / localStorage zum Speichern des Anmeldestatus kann in bestimmten Situationen zu Fehlern führen.
Firebase zeichnet bereits Anmeldeinformationen bei localStorage auf, einschließlich expirationTime und refreshToken.
Daher werde ich den von Vue erstellten Hook und die Firebase-API verwenden, um den Anmeldestatus zu überprüfen.
Wenn das Token abgelaufen ist, aktualisiert die API das Token für uns.
So können wir sicherstellen, dass die Anmeldestatusanzeige in unserer App Firebase entspricht.

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
quelle
der beste, offizielle und empfohlene Ansatz gegen diese Situation
alijunior
7

Der Vuex-Status wird gespeichert. Durch das Laden der Seite wird dieser aktuelle Status gelöscht. Aus diesem Grund bleibt der Status beim erneuten Laden nicht bestehen.

Aber das vuex-persistedstatePlugin löst dieses Problem

npm install --save vuex-persistedstate

Importieren Sie dies nun in den Store.

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()]
});

Es funktionierte perfekt mit einer einzigen Codezeile: plugins: [createPersistedState()]

Rijo
quelle
6

Zustand aufsetzen:

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

Mutationen anziehen:

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

funktioniert gut für mich!

Leonardo Filipe
quelle
1

Ich habe dieses Problem gelöst, indem ich meine Header jedes Mal zurückgesetzt habe, wenn ich neu lade und auch Benutzerdaten abrufe. Ich weiß nicht, was besser ist ...

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
quelle