Состояние Vuex при обновлении страницы

Мое приложение использует Firebase API для аутентификации пользователя, сохраняя статус входа в систему как логическое значение в состоянии Vuex.

Когда пользователь входит в систему, я устанавливаю статус входа и, соответственно, условно отображаю кнопку входа / выхода.

Но когда страница обновляется, состояние приложения vue теряется и сбрасывается до значения по умолчанию.

Это вызывает проблему, поскольку даже когда пользователь вошел в систему и страница обновлена, статус входа снова устанавливается на false, и кнопка входа отображается вместо кнопки выхода даже хотя пользователь остается авторизованным ....

Что мне делать, чтобы предотвратить такое поведение

Должен ли я использовать файлы cookie или доступно другое лучшее решение ...

    -

person boomboxboy    schedule 26.03.2017    source источник
comment
Для этого я использую любое локальное хранилище. Это могут быть файлы cookie или что-то еще   -  person Hammerbot    schedule 26.03.2017
comment
@El_Matella, кроме файлов cookie, какой еще метод вы используете для локального хранения данных   -  person boomboxboy    schedule 26.03.2017
comment
Как правило, я использую пакет npm для локального хранилища, который может выбрать для меня лучший способ хранения данных: npmjs.com/package/local-storage API - это упрощенный способ взаимодействия со всем, что связано с localStorage. Обратите внимание, что когда localStorage не поддерживается в текущем браузере, откат к хранилищу в памяти используется прозрачно.   -  person Hammerbot    schedule 26.03.2017
comment
@El_Matella большое спасибо ... я посмотрю   -  person boomboxboy    schedule 26.03.2017


Ответы (6)


Это известный вариант использования. Есть разные решения.

Например, можно использовать 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

person sobolevn    schedule 26.03.2017
comment
Спасибо ... Только что заглянул на страницу плагина на github ... Еще раз спасибо - person boomboxboy; 26.03.2017
comment
Вам нужно что-то сделать для установки / получения данных? При перезагрузке мои данные сбрасываются до значений по умолчанию. Просто установка через this. $ Store.state.user, проверенные объекты и простые строки - не повезло. - person DogCoffee; 06.05.2017
comment
Поскольку файлы cookie передаются между клиентом и сервером, я бы, вероятно, вместо этого посмотрел на локальное хранилище ... - person James Westgate; 09.08.2018
comment
как сохранить состояние aws-ampify? так как он слишком велик для файлов cookie, а локальное хранилище не будет работать в частном режиме сафари - person hounded; 09.09.2018
comment
@hounded Я тоже сталкиваюсь с той же проблемой, нашел для нее какое-нибудь решение? - person Adil; 05.08.2019
comment
перешел на эту методологию dev.to/dabit3/ < / а> - person hounded; 11.08.2019

При создании состояния 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();, когда пользователь выходит из системы вручную.

person James Westgate    schedule 13.11.2019
comment
Я удивлен, что решение для печенья получает так много звезд. Я думаю, что это решение намного лучше, поскольку оно автоматически очищает все состояние при закрытии окна браузера. Мне не нравится отправлять данные о моем состоянии в виде файлов cookie на сервер, а также я не хочу сохранять конфиденциальные данные при закрытии окна браузера. - person Mark Hagers; 11.02.2020
comment
Вы также ограничены в общей сложности 8 КБ для ваших заголовков, включая файлы cookie. - person James Westgate; 19.02.2020
comment
@MarkHagers, и он изначально поддерживается с IE8! Нет необходимости загружать дополнительный код. - person Fabian von Ellerts; 21.02.2020
comment
Я получал сообщение об ошибке vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON - person Akin Hwan; 20.06.2020
comment
@Akin - ошибка предполагает, что у вас есть циклическая ссылка в вашем состоянии, объект ссылается на другой объект, который в конечном итоге ссылается на первый объект. - person James Westgate; 21.06.2020
comment
При использовании Typescript у меня возникает ошибка при обновлении: vuex-persistedstate.es.js? 0e44: 1 Uncaught TypeError: r.propertyIsEnumerable не является функцией - person Dan M. CISSOKHO; 17.12.2020

Состояние 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()]
});

Он отлично работал с одной строкой кода: plugins: [createPersistedState()]

person Rijo    schedule 28.03.2020
comment
с vuex create store: const store = createStore ({/*...*/ plugins: [createPersistedState ()],}); - person user1706618; 11.06.2021
comment
это самый простой подход без добавления другого пакета. Оно работает! - person Jhon Rey; 18.07.2021

Я думаю, что использование cookie / localStorage для сохранения статуса входа в систему может вызвать некоторую ошибку в некоторых ситуациях.
Firebase уже записывает информацию для входа в localStorage для нас, включая expirationTime и refreshToken.
Поэтому я буду использовать Vue created hook и Firebase api для проверки статус входа в систему.
Если срок действия токена истек, 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.');
            }
        });
    },
});
person Andrew - oahehc    schedule 30.06.2017
comment
лучший, официальный и рекомендуемый подход к этой ситуации - person alijunior; 28.06.2020

поставить на состояние:

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

поставить на мутации:

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

у меня отлично работает!

person Leonardo Filipe    schedule 30.11.2018

Я решил это, сбрасывая свои заголовки каждый раз, когда я перезагружаюсь, также получаю пользовательские данные, я не знаю, что лучше ...

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

})
person Alenn G'Kar    schedule 27.06.2017
comment
Это решение сработало для меня - person Rohit Nair; 30.03.2021