programing

스토어 변경 시 구성 요소가 업데이트되지 않음 - Vuex

randomtip 2022. 10. 3. 17:39
반응형

스토어 변경 시 구성 요소가 업데이트되지 않음 - Vuex

TLDR:

도움이 된다면 제 문제를 설명하는 동영상을 녹화했습니다.https://youtu.be/Qf9Q4zIaox8

상점 변경 시 Navbar 구성 요소가 업데이트되지 않습니다.

v-if와 v-else를 사용하여 구성 요소를 두 섹션으로 분리했습니다.사용자가 v-if에 로그인한 경우 및 로그인하지 않은 경우 v-else가 표시됩니다.

로그인하면 서버가 인증되고 클라이언트는 스토어에 변환을 커밋하여 사용자와 클라이언트토큰을 설정합니다.이 설정을 하면 "userIsLoggedIn"이라는 상태의 속성이 true로 설정됩니다.이 속성은 네비게이션바 컴포넌트에서 계산됩니다.알 수 없는 이유로 사용자가 로그인하면 Navbar 컴포넌트가 업데이트되지 않습니다(isLogged에도 불구하고).in property that true) 페이지를 새로 고치지 않는 한.

내비게이션 구성 요소:

<template>
    <div class="navbar">
        <div class="container">
            <div class="navbar-brand">
                <h1 class="navbar-item">
                    <router-link to="/" class="has-text-black">Logo</router-link>
                </h1>
            </div>

            <div class="navbar-menu">
                <div class="navbar-end" v-if="isLoggedIn">
                    <div class="navbar-item">
                        <router-link to="/play" class="has-text-black">Play</router-link>
                    </div>
                    <div class="navbar-item">
                        {{user.balance.toFixed(2)}}
                    </div>
                    <div class="navbar-item has-dropdown is-hoverable">
                        <a class="navbar-link">
                            {{user.username}}
                        </a>

                        <div class="navbar-dropdown">
                            <div class="navbar-item">Profile</div>
                            <div class="navbar-item">Deposit</div>
                            <div class="navbar-item" @click="logout">Logout</div>
                        </div>
                    </div>
                    <div class="navbar-item">
                        FAQ
                    </div>
                </div>

                <div class="navbar-end" v-else>
                    <div class="navbar-item">
                        <router-link to="/login" class="has-text-black">Login</router-link>
                    </div>
                    <div class="navbar-item">
                        <router-link to="/register" class="has-text-black">Register</router-link>
                    </div>
                    <div class="navbar-item">FAQ</div>
                </div>
            </div>
        </div> <!-- container -->
    </div> <!-- navbar -->
</template>

<script>

import {mapGetters} from "vuex";
export default {
    name: "Navbar",
    data() {
        return {
            user: this.$store.state.user,
        }
    },
    computed: {
        ...mapGetters([
            "isLoggedIn",
        ])
    },

    methods: {
        logout() {
            this.$store.dispatch("setToken", null);
            this.$store.dispatch("setUser", null);
            this.$router.push({
                path: "/"
            })
        }
    }
}
</script>

Vuex 스토어:

import Vue from "vue"; 
import Vuex from "vuex";
import createPersistedState from "vuex-persistedstate"

Vue.use(Vuex);

export default new Vuex.Store({
    strict: true, 
    plugins: [
        createPersistedState()
    ],
    state: {
        token: null, 
        user: null, 
        isUserLoggedIn: false, 
    },
    getters: {
        isLoggedIn(state) {
            return state.isUserLoggedIn;
        }
    },
    
    mutations: {
        setToken(state, token) {
            state.token = token;
            if (token) {
                state.isUserLoggedIn = true;
            } else {
                state.isUserLoggedIn = false;
            }
        },
        setUser(state, user) {
            state.user = user; 
        }
    },
    actions: {
        setToken ({commit}, token) {
            commit("setToken", token);
        },
        setUser ({commit}, user) {
            commit("setUser", user);
        }
    }
})

로그인 컴포넌트:

<template>
  <div class="hero is-large">
      <div class="container">
          <div class="hero-body">
            
              <div class="field">
                  <div class="notification is-warning" v-show="error">{{error}}</div>
              </div>

              <h1 class="title">Login</h1>


              <div class="field">
                  <label for="username" class="name">Username</label>
                  <input type="text" class="input" name="username" v-model="username">
              </div>

              <div class="field">
                  <label for="username" class="name">Password</label>
                  <input type="password" class="input" name="password" v-model="password">
              </div>

              <div class="field">
                  <button class="button is-link"
                          @click="login"
                          v-bind:class="{'is-loading': pending}">Login</button>
              </div>
          </div>
      </div>
  </div>
</template>

<script>

import AuthenticationService from "../Services/AuthenticationService";

export default {
  name: "Login", 

  data () {
      return {
          username: "",
          password: "", 
          error: null, 
          pending: false, 
      }
  }, 
  methods: {
      async login () {
          try {
            // SET LOADING SPINNER
            this.pending = true; 

            // API REQUEST
            const response = await AuthenticationService.login({
                username: this.username,
                password: this.password, 
            });

            console.log(response);

            // CLEAR FORM
            this.pending = false; 
            this.username = "";
            this.password = ""; 

            this.$store.dispatch("setToken", response.data.token);
            this.$store.dispatch("setUser", response.data.user);

            this.$router.push({
                name: "Landing"
            })
          } catch (error) {
              console.log(error);
          }
      }
  }
}
</script>

뭐가 잘못됐는지 찾은 것 같아요.사용자가 로그인 했을 때 isUserLogged를 설정하지 않았습니다.사실대로.따라서 액션을 수행하고 변환하여 isUserLogged로 변경합니다.사용자가 정상적으로 로그인했을 때 In to true.

액션.

setUserLogged ({commit}) {
 commit("setUserLogged", true);
}

돌연변이

setUserLogged(state, payload) {
 state.isUserLoggedIn = true
}

그런 다음 해당 행의 Login 컴포넌트에서 이를 변경합니다.

this.$store.dispatch("setToken", response.data.token);
this.$store.dispatch("setUser", response.data.user);

다음과 같이 입력합니다.

this.$store.dispatch("setToken", response.data.token);
this.$store.dispatch("setUser", response.data.user);
this.$store.dispatch("setUserLogged");

언급URL : https://stackoverflow.com/questions/49224266/component-not-updating-on-store-change-vuex

반응형