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

106

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

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

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

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

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

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

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

Ответы:

110

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

Например, можно использовать 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 ... Еще раз
спасибо
8
Вам нужно что-то сделать для установки / получения данных? При перезагрузке мои данные сбрасываются до значений по умолчанию. Просто установка через this. $ Store.state.user, проверенные объекты и простые строки - не повезло.
DogCoffee
6
Поскольку файлы cookie передаются между клиентом и сервером, я бы, вероятно, вместо этого посмотрел на локальное хранилище ...
Джеймс Вестгейт
как сохранить состояние aws-ampify? поскольку он слишком велик, чтобы поместиться в файлы cookie, а локальное хранилище не будет работать в частном режиме сафари
преследовал
@hound Я тоже сталкиваюсь с той же проблемой, нашел ли решение для этого?
Адиль
54

При создании состояния 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 на сервер, а также я не хочу сохранять конфиденциальные данные при закрытии окна браузера.
Марк Хейджерс,
Вы также ограничены в общей сложности 8 КБ для ваших заголовков, включая файлы cookie.
Джеймс Вестгейт
2
@MarkHagers, и он изначально поддерживается с IE8! Не нужно загружать дополнительный код.
Фабиан фон Эллертс,
1
Я получаю сообщение об ошибке vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
Акин Хван
1
@Akin - ошибка предполагает, что у вас есть циклическая ссылка в вашем состоянии, объект ссылается на другой объект, который в конечном итоге ссылается на первый объект.
Джеймс Вестгейт,
11

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

Rijo
источник
10

Я думаю, что использование 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.');
            }
        });
    },
});
Андрей - oahehc
источник
лучший, официальный и рекомендуемый подход к этой ситуации
alijunior
8

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

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

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

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

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

Леонардо Филипе
источник
1

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

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

})
Аленн Г'Кар
источник