สถานะ Vuex ในการรีเฟรชหน้า


113

แอปของฉันใช้ Firebase API สำหรับการตรวจสอบผู้ใช้โดยบันทึกสถานะการเข้าสู่ระบบเป็นค่าบูลีนในสถานะ Vuex

เมื่อผู้ใช้เข้าสู่ระบบฉันตั้งค่าสถานะการเข้าสู่ระบบและแสดงปุ่มเข้าสู่ระบบ / ออกจากระบบตามเงื่อนไข

แต่เมื่อรีเฟรชหน้าแล้วสถานะของแอป vue จะหายไปและรีเซ็ตเป็นค่าเริ่มต้น

สิ่งนี้ทำให้เกิดปัญหาแม้ว่าผู้ใช้จะเข้าสู่ระบบและเพจได้รับการรีเฟรชสถานะการเข้าสู่ระบบจะถูกตั้งค่ากลับเป็นเท็จและปุ่มล็อกอินจะแสดงแทนปุ่มล็อกเอาต์แม้ว่าผู้ใช้จะยังคงล็อกอินอยู่ก็ตาม ....

ฉันจะทำอย่างไรเพื่อป้องกันพฤติกรรมนี้

ฉันจะใช้คุกกี้ได้ หรือไม่หรือวิธีการอื่นที่ดีกว่านี้ ...

    -

2
ฉันใช้ที่จัดเก็บข้อมูลในเครื่องชนิดใดก็ได้เพื่อจัดการสิ่งนั้น นั่นอาจเป็นคุกกี้หรืออย่างอื่นก็ได้
Hammerbot

@El_Matella นอกเหนือจากคุกกี้คุณใช้วิธีการอื่นในการจัดเก็บข้อมูลในเครื่อง
boomboxboy

1
โดยทั่วไปฉันใช้แพ็คเกจ npm ที่จัดเก็บในตัวเครื่องซึ่งสามารถเลือกวิธีที่ดีที่สุดในการจัดเก็บข้อมูลสำหรับฉัน: npmjs.com/package/local-storage "API เป็นวิธีที่ง่ายในการโต้ตอบกับทุกสิ่งใน localStorage โปรดทราบว่าเมื่อ localStorage เป็น ไม่ได้รับการสนับสนุนในเบราว์เซอร์ปัจจุบันทางเลือกสำรองของที่เก็บในหน่วยความจำจะถูกใช้อย่างโปร่งใส "
Hammerbot

@El_Matella ขอบคุณมาก ... ฉันจะได้ดู
boomboxboy

คำตอบ:


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

9
คุณต้องทำอะไรเพื่อตั้งค่า / รับข้อมูลหรือไม่? เมื่อโหลดซ้ำข้อมูลของฉันจะถูกรีเซ็ตเป็นค่าเริ่มต้น เพียงแค่ตั้งค่าผ่านทางนี้ $ store.state.user วัตถุที่พยายามและสตริงง่ายๆ - ไม่มีโชค
DogCoffee

6
เนื่องจากคุกกี้ถูกส่งระหว่างไคลเอนต์และเซิร์ฟเวอร์ฉันอาจจะดูที่การจัดเก็บในตัวเครื่องแทน ...
James Westgate

ฉันจะบันทึกสถานะของ aws-amplify ได้อย่างไร เนื่องจากมีขนาดใหญ่ที่จะพอดีกับคุกกี้และพื้นที่เก็บข้อมูลในเครื่องจะไม่ทำงานในโหมดส่วนตัวของซาฟารี
ไล่ล่า

@hounded ฉันกำลังเผชิญกับปัญหาเดียวกันพบวิธีแก้ปัญหานี้หรือไม่?
Adil

65

เมื่อสร้างสถานะ VueX ของคุณให้บันทึกลงในพื้นที่เก็บข้อมูลเซสชันโดยใช้ปลั๊กอินvuex-persistedstate ด้วยวิธีนี้ข้อมูลจะหายไปเมื่อปิดเบราว์เซอร์ หลีกเลี่ยงการใช้คุกกี้เนื่องจากค่าเหล่านี้จะเดินทางระหว่างไคลเอนต์และเซิร์ฟเวอร์

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
ฉันแปลกใจที่โซลูชันคุกกี้ได้รับดาวมากมาย ฉันคิดว่าวิธีนี้ดีกว่ามากเนื่องจากจะล้างสถานะทั้งหมดโดยอัตโนมัติเมื่อปิดหน้าต่างเบราว์เซอร์ ฉันไม่ชอบส่งข้อมูลสถานะของฉันเป็นคุกกี้ไปยังเซิร์ฟเวอร์และฉันก็ไม่ต้องการเก็บข้อมูลที่ละเอียดอ่อนเมื่อหน้าต่างเบราว์เซอร์ปิดลง
Mark Hagers

คุณยังถูก จำกัด ไว้ที่ 8k โดยรวมส่วนหัวของคุณรวมถึงคุกกี้
James Westgate

2
@MarkHagers และได้รับการสนับสนุนโดยกำเนิดตั้งแต่ IE8! ไม่ต้องโหลดโค้ดพิเศษ
Fabian von Ellerts

1
ฉันได้รับข้อผิดพลาด vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
Akin Hwan

1
@Akin - ข้อผิดพลาดแสดงให้เห็นว่าคุณมีการอ้างอิงแบบวงกลมในสถานะของคุณอ็อบเจ็กต์อ้างอิงอ็อบเจ็กต์อื่นซึ่งในที่สุดก็อ้างอิงกลับไปที่อ็อบเจ็กต์แรก
James Westgate

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

ทำงานได้อย่างสมบูรณ์แบบด้วยรหัสบรรทัดเดียว: plugins: [createPersistedState()]


10

ฉันคิดว่าการใช้คุกกี้ / 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.');
            }
        });
    },
});

แนวทางที่ดีที่สุดเป็นทางการและแนะนำสำหรับสถานการณ์นี้
อาวุโส

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.