programing

Vuex가 기존 양식 데이터를 상태별로 로드하여 편집

prostudy 2022. 8. 27. 09:15
반응형

Vuex가 기존 양식 데이터를 상태별로 로드하여 편집

이 튜토리얼에 따라 Vue를 학습했습니다.이 튜토리얼은 완료되어 동작하고 있습니다만, 어려운 변경을 시도하고 있습니다.

https://savvyapps.com/blog/definitive-guide-building-web-app-vuejs-firebase

따라서 사용자 프로필이 있는 "설정" 페이지가 있습니다(이름 등을 편집할 수 있습니다)."settings" / "profile" 페이지가 로드되면 폼에서 기존 데이터를 로드하여 수정하고 저장을 누릅니다.

현재 플레이스 홀더로 로드됩니다.:placeholder="userProfile.name"·플레이스 홀더로서가 아니라, 폼을 실제의 값으로 채우고 싶다.

이렇게 하는 것은 터무니없이 간단해야 할 것 같지만 우아하게 작동시킬 수 없습니다.

설정.표시하다

<template>
  <section id="settings">
    <div class="col1">
      <h3>Settings</h3>
      <p>Update your profile</p>

      <transition name="fade">
        <p v-if="showSuccess" class="success">profile updated</p>
      </transition>

      <form @submit.prevent>
        <label for="name">Name</label>
        <input v-model.trim="name" type="text" id="name" />

        <label for="title">Job Title</label>
        <input v-model.trim="title" type="text" id="title" />

        <button @click="updateProfile()" class="button">Update Profile</button>
      </form>
    </div>
  </section>
</template>

<script>
import { mapState } from "vuex";

export default {
  data() {
    return {
      name: "",
      title: "",
      showSuccess: false,
    };
  },
  computed: {
    ...mapState(["userProfile"]),
  },
  methods: {
    updateProfile() {
      this.$store.dispatch("updateProfile", {
        name: this.name !== "" ? this.name : this.userProfile.name,
        title: this.title !== "" ? this.title : this.userProfile.title,
      });

      this.name = "";
      this.title = "";

      this.showSuccess = true;

      setTimeout(() => {
        this.showSuccess = false;
      }, 2000);
    },
  },
};
</script>

<style lang="scss" scoped>
</style>

데이터 섹션을 이 섹션으로 변경해 보았습니다.이 섹션은 페이지를 나갔다가 다시 돌아가면 기능합니다만, 페이지를 새로 고치면(F5) 페이지를 나갔다가 다시 돌아올 때까지 필드가 비어 있습니다.

data() {
    return {
      name: this.$store.state.userProfile.name,
      title: this.$store.state.userProfile.title,
      showSuccess: false,
    };
  },

그리고 만약 당신이 그걸 보고 싶다면, 여기 내 가게가 있다.

store/index.displaces

import Vue from "vue";
import Vuex from "vuex";
import * as fb from "../firebase";
import router from "../router/index";

Vue.use(Vuex);

// realtime firebase connection
fb.postsCollection.orderBy("createdOn", "desc").onSnapshot((snapshot) => {
  let postsArray = [];

  snapshot.forEach((doc) => {
    let post = doc.data();
    post.id = doc.id;

    postsArray.push(post);
  });

  store.commit("setPosts", postsArray);
});

const store = new Vuex.Store({
  state: {
    userProfile: {},
    posts: [],
  },
  mutations: {
    setUserProfile(state, val) {
      state.userProfile = val;
    },
    setPosts(state, val) {
      state.posts = val;
    },
  },
  actions: {
    async signup({ dispatch }, form) {
      // sign user up
      const { user } = await fb.auth.createUserWithEmailAndPassword(
        form.email,
        form.password
      );

      // create user profile object in userCollections
      await fb.usersCollection.doc(user.uid).set({
        name: form.name,
        title: form.title,
      });

      // fetch user profile and set in state
      dispatch("fetchUserProfile", user);
    },
    async login({ dispatch }, form) {
      // sign user in
      const { user } = await fb.auth.signInWithEmailAndPassword(
        form.email,
        form.password
      );

      // fetch user profile and set in state
      dispatch("fetchUserProfile", user);
    },
    async logout({ commit }) {
      await fb.auth.signOut();

      // clear userProfile and redirect to /login
      commit("setUserProfile", {});
      router.push("/login");
    },
    async fetchUserProfile({ commit }, user) {
      // fetch user profile
      const userProfile = await fb.usersCollection.doc(user.uid).get();

      // set user profile in state
      commit("setUserProfile", userProfile.data());

      // change route to dashboard
      if (router.currentRoute.path === "/login") {
        router.push("/");
      }
    },
    async createPost({ state }, post) {
      await fb.postsCollection.add({
        createdOn: new Date(),
        content: post.content,
        userId: fb.auth.currentUser.uid,
        userName: state.userProfile.name,
        comments: 0,
        likes: 0,
      });
    },
    async likePost(context, { id, likesCount }) {
      const userId = fb.auth.currentUser.uid;
      const docId = `${userId}_${id}`;

      // check if user has liked post
      const doc = await fb.likesCollection.doc(docId).get();
      if (doc.exists) {
        return;
      }

      // create post
      await fb.likesCollection.doc(docId).set({
        postId: id,
        userId: userId,
      });

      // update post likes count
      fb.postsCollection.doc(id).update({
        likes: likesCount + 1,
      });
    },
    async updateProfile({ dispatch }, user) {
      const userId = fb.auth.currentUser.uid;
      // update user object
      /*const userRef = */await fb.usersCollection.doc(userId).update({
        name: user.name,
        title: user.title,
      });

      dispatch("fetchUserProfile", { uid: userId });

      // update all posts by user
      const postDocs = await fb.postsCollection
        .where("userId", "==", userId)
        .get();
      postDocs.forEach((doc) => {
        fb.postsCollection.doc(doc.id).update({
          userName: user.name,
        });
      });

      // update all comments by user
      const commentDocs = await fb.commentsCollection
        .where("userId", "==", userId)
        .get();
      commentDocs.forEach((doc) => {
        fb.commentsCollection.doc(doc.id).update({
          userName: user.name,
        });
      });
    },
  },
  modules: {},
});

export default store;

편집

이 데이터가 Firebase Firestore에서 주(州)로 로드되고 있다고 말했어야 했어요.컴포넌트에 data()를 설정할 때까지 데이터가 로드되지 않습니다.콘솔 로그를 추가했습니다.

Fetching user profile.. Settings.vue?e12e:29
Setting Data... index.js?4360:75
Performing setUserProfile commit.. index.js?4360:29
Setting user profile in state, last step..

다시 말씀드리지만 Vue에 대해 잘 모르기 때문에 그 순서를 가장 잘 변경할 수 없습니다.

v-model 전달되는 모든 값을 가져오고 설정합니다.상태 속성을 편집하는 경우,<input>의 값은 상태 속성의 값을 변경(변환)하려고 합니다.그리고 그것은 불변의 원리를 깨트릴 것이다.
여기서의 해결책은 계산된 속성을v-modelgetter와 setter를 사용하여 컴포넌트의 값 취득처와 갱신방법을 지정합니다.

디폴트computed속성은 getter만 포함하는 줄임말입니다.기본적으로는

computed: {
  name() {
    return this.$store.state.userProfile.name
  }
}

...는 다음과 같이 쓸 수 있습니다.

computed: {
  name: {
    get() {
      return this.$store.state.userProfile.name
    }
  }
}

필요한 것은 상태가 갱신되도록 적절한 변환을 커밋하는 세터를 추가하는 것입니다.

computed: {
  ...mapState(["userProfile"]),
  name: {
    get() {
      return this.userProfile.name
    },
    set(val) {
      this.$store.commit('setUserProfile', {
        ...this.userProfile,
        name: val
      });
    }
  },
  title: {
    get() {
      return this.userProfile.title
    },
    set(val) {
      this.$store.commit('setUserProfile', {
        ...this.userProfile,
        title: val
      });
    }
  }
}

계산 세터는 여기에 기재되어 있습니다.


[1] - Vuex를 사용하는 이유는 컴포넌트가 데이터를 직접 변경할 수 없도록 하기 위해서입니다.대신 해당 데이터를 사용하는 모든 구성 요소가 변경 내용을 알 수 있도록 해당 상태에 돌연변이를 커밋해야 합니다.당신이 허락한다면v-model데이터를 직접 바꾸면 불변의 원칙을 깨는 셈이죠 그래서 당신의 주가 진실의 유일한 원천이 되지 않게 되는 거죠

다음 두 가지 사항을 고려해야 합니다. 먼저 상태 상자 getter의 변수에서 값을 가져오는 경우(좋은 vuex 프랙티스로서).

Vuex 파일:

const store = new Vuex.Store({
  state: {
    userProfile: {},
    posts: [],
  },

  getters:{
    getUserProfile: (state) => state.userProfile
  }

정착촌.vue So에서 원하는 것을 달성하려면 마운트된 메서드 내의 data()에 변수를 로드하면 됩니다.

export default {
  data() {
    return {
      name: "",
      title: "",
      showSuccess: false,
    };
  },
  computed: {
    ...mapState(["getUserProfile"]),
  },

  mounted(){
   this.name = getUserProfile.name
  }

따라서 사용자가 로드된 데이터를 잃지 않고 페이지를 새로 고칠 것으로 예상할 경우 페이지를 새로 고치면 vuex 시스템도 다시 시작되므로 vuex만 사용할 수 없습니다.페이지를 새로 고친 후 로드된 데이터를 유지 관리하려면 vuex 또는 유사한 솔루션과 함께 로컬 스토리지를 사용하십시오.

타이밍에 맞춰야 하니까

데이터 값을 주의 감시자에게 바인딩하는 것이 좋습니다.사용자의 컴포넌트는 상태가 갱신될 때마다 수신 대기만 하고 그에 따라 데이터를 갱신합니다.

export default {
  data() {
    return {
      name: "",
      title: "",
      showSuccess: false,
    };
  },
  computed: {
    ...mapState(["userProfile"]),
  },
  watch: {
    userProfile: {
      handler({ name, title }) {
        this.name = name;
        this.title = title;
      },
      deep: true, // deep is to listen to objects properly
      immediate: true // immediate so the watcher triggers right away when the component is mounted
    }
  },
  methods: {
    updateProfile() {
      this.$store.dispatch("updateProfile", {
        name: this.name !== "" ? this.name : this.userProfile.name,
        title: this.title !== "" ? this.title : this.userProfile.title,
      });
      
            /*  I just wouldn't reset the values here since they'll be updated in the watcher
      this.name = "";
      this.title = ""; */

      this.showSuccess = true;

      setTimeout(() => {
        this.showSuccess = false;
      }, 2000);
    },
  },
};

언급URL : https://stackoverflow.com/questions/64018053/vuex-load-existing-form-data-from-state-to-edit

반응형