ページ更新時のVuexの状態


113

私のアプリはユーザー認証にFirebaseAPIを使用しており、ログインステータスをブール値としてVuex状態で保存しています。

ユーザーがログインすると、ログインステータスを設定し、それに応じて[ログイン/ログアウト]ボタンを条件付きで表示します。

ただし、ページが更新されると、vueアプリの状態は失われ、デフォルトにリセットされます

これにより、ユーザーがログインしてページが更新された場合でも、ログインステータスfalseに戻され、ユーザーがログインしたままでもログアウトボタンの代わりにログインボタンが表示されるため、問題が発生します。

この動作を防ぐにはどうすればよいですか

クッキーを使用します か、それとも他のより良い解決策が利用可能です...

    -

2
私はそれを処理するためにあらゆる種類のローカルストレージを使用します。それはクッキーか何か他のものである可能性があります
Hammerbot 2017年

@El_Matella Cookieとは別に、データをローカルに保存するために他にどのような方法を使用していますか
boomboxboy 2017年

1
一般的に、私はデータを保存するための最良の方法を選択できるローカルストレージnpmパッケージを使用します:npmjs.com/package/local-storage "APIは、localStorageのすべてのものと対話するための単純化された方法です。localStorageが現在のブラウザではサポートされていないため、メモリ内ストアへのフォールバックは透過的に使用されます。」
Hammerbot 2017年

@El_Matellaありがとうございました...見て
いき

回答:


115

これは既知のユースケースです。さまざまな解決策があります。

たとえば、を使用できますvuex-persistedstate。これは、vuexページの更新の間に状態を処理および保存するためのプラグインです。

サンプルコード:

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

ここで行うことは簡単です。

  1. インストールする必要があります js-cookie
  2. 上でgetState私たちから保存された状態をロードしようCookies
  3. setStateに私たちの状態を保存し、我々Cookies

ドキュメントとインストール手順:https//www.npmjs.com/package/vuex-persistedstate


ありがとう...プラグインのgithubページを見ていました...もう一度ありがとう
boomboxboy 2017年

9
データの設定/取得に特別なことをする必要がありますか?リロードすると、データはデフォルトにリセットされます。this。$ store.state.userを介して設定するだけで、オブジェクトと単純な文字列を試しましたが、運がありません。
DogCoffee 2017年

6
クッキーは、クライアントとサーバーの間で送信されているので、私はおそらく...代わりに、ローカルストレージになります
ジェームズウエストゲート

aws-amplifyの状態を保存するにはどうすればよいですか?クッキーに収まるには大きすぎて、localstorageはサファリプライベートモードでは機能しません
2018

@hounded私も同じ問題に直面しています、これに対する解決策を見つけましたか?
アディル

63

VueX状態を作成するときは、vuex-persistedstateプラグインを使用してセッションストレージに保存します。このように、ブラウザを閉じると情報が失われます。これらの値はクライアントとサーバー間を移動するため、Cookieの使用は避けてください。

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

sessionStorage.clear();ユーザーが手動でログアウトするときに使用します。


13
クッキーソリューションが非常に多くの星を獲得していることに驚いています。このソリューションは、ブラウザウィンドウを閉じるとすべての状態を自動的にクリアするため、はるかに優れていると思います。状態データをCookieとしてサーバーに送信するのは好きではありません。また、ブラウザーウィンドウが閉じたときに機密データを保持したくありません。
MarkHagers20年

また、Cookieを含むヘッダーの合計は8kに制限されています。
ジェームズ・ウエストゲート

2
@MarkHagersとそれはIE8以来ネイティブにサポートされています!余分なコードをロードする必要はありません。
Fabian vonEllerts20年

1
エラーが発生していました vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
AkinHwan20年

1
@ Akin-エラーは、状態に循環参照があることを示しています。オブジェクトは別のオブジェクトを参照しており、最終的には最初のオブジェクトを参照しています。
JamesWestgate20年

13

Vuexの状態はメモリに保持されます。ページの読み込みにより、この現在の状態が削除されます。これが、リロード時に状態が持続しない理由です。

しかし、vuex-persistedstateプラグインはこの問題を解決します

npm install --save vuex-persistedstate

これをストアにインポートします。

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

1行のコードで完全に機能しました。 plugins: [createPersistedState()]


10

ログインステータスを保存するためにcookies / localStorageを使用すると、状況によってはエラーが発生する可能性があると思います。
Firebaseは、expirationTimeとrefreshTokenを含むログイン情報をlocalStorageにすでに記録しています。
したがって、Vueで作成されたフックとFirebaseAPIを使用してログインステータスを確認します。
トークンの有効期限が切れている場合、APIはトークンを更新します。
そのため、アプリのログインステータスの表示が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.');
            }
        });
    },
});

この状況に対する最善の、公式の、そして推奨されるアプローチ
alijunior 2020年

8

状態に置く:

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

突然変異を起こす:

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

私にとってはうまくいきます!


2

再ロードするたびにヘッダーをリセットしてユーザーデータをフェッチすることでこれを解決しましたが、何が良いのかわかりません...

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

})
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.