简体   繁体   中英

Vue component is not reactive

My issue is that when i make a request to delete an item from my component, the component does not automatically update to show new state.

template

     <div v-for="house in allHouses" :key="house.id" >
       <div class="edit-delete-wrap" v-if="house.madeByMe">
       <img class="edit-delete-btn" src="/images/edit.png" alt="">
       <img @click="deleteHouse(house.id)"  class="edit-delete- 
           btn" src="/images/delete.png" alt="" srcset="">
       </div>
        {{house.street}}
     </div>

this is an example of the template, it is card with a house details on it, there is a button to delete this item from the list.

Scripts for house card component

<script>
import {mapActions, mapGetters} from 'vuex'
export default {
    name: "HouseCard",
    props: ["searchHouses", "sortHouses"],
    computed: {
    ...mapGetters(['allHouses']),
   
    },
    methods: {
 ...mapActions(['fetchHouses', 'houseDetail', 'deleteHouse']),
    },
    created(){
    this.fetchHouses()
  },

}
</script>

The list data comes from the allHouses houses computed function.

vuex store

import api from "../../api/houses";

const state = {
  houses: [],
  selectedHouse: [],
};

const getters = {
  allHouses: (state) => state.houses,
  selectedHouse: (state) => state.selectedHouse,
};

const actions = {
  async fetchHouses({ commit }) {
    const response = await api.fetchHouses();
    commit("setHouses", response.data);
    console.log(response.data);
  },
  createNewHouse(_, formData) {
    api.createNewHouse(formData);
  },
  async deleteHouse(_, house) {
    api.deleteHouse(house)
    const response = await api.fetchHouses();
    commit("setHouses", response.data);
  },
  async houseDetail({ commit }, id) {
    const response = await api.fetchHouses();

    response.data.forEach((house) => {
      if (house.id === id) {
        console.log(house);
        commit("setSelectedHouse", house);
      }
    });
  },
};

const mutations = {
  setHouses: (state, houses) => {
    state.houses = houses;
  },
  setSelectedHouse: (state, selectedHouse) => {
    state.selectedHouse = selectedHouse;
  },
};

export default {
  state,
  getters,
  actions,
  mutations,
};

here is the store where i have the manage the state of the app, in the deleteHouse action function i delete the house then try to get a new api response and set the state of houses to the new updated state of the houses array.

api

import axios from "axios";

const API_KEY = "xxxxxxxxx";

export default {
  fetchHouses() {
    return axios.get("https://api.intern.d-tt.nl/api/houses", {
      headers: {
        "X-Api-Key": API_KEY,
      },
    });
  },
  async deleteHouse(id) {
    axios
      .delete(`https://api.intern.d-tt.nl/api/houses/${id}`, {
        headers: {
          "X-Api-Key": API_KEY,
        },
      })
      .then(() => {
        console.log("successful deletion");
      });
  },
  createNewHouse(formData) {
    console.log("api page", formData);
    const image = formData.houseImage;

    return axios
      .post("https://api.intern.d-tt.nl/api/houses", formData.form, {
        headers: {
          "X-Api-Key": API_KEY,
        },
      })
      .then((res) => {
        console.log("REACHED FIRST POST");
        const id = res.data.id;
        const formData = new FormData();

        formData.append("image", image[0]);
        axios
          .post(
            `https://api.intern.d-tt.nl/api/houses/${id}/upload`,
            formData,
            {
              headers: {
                "X-Api-Key": API_KEY,
              },
            }
          )
          .then(console.log("success"))
          .catch((err) => console.log(err));
      })
      .catch((err) => {
        console.log(err);
      });
  },
};

here is the api file that i use to make all api requests. i hope this information helps.

Per @RenauldC5, you didn't provide enough information about your allHouses getter or where and how the data gets into the store or where setHouses stores the data, and how.

However a question/tips to guide you:

  1. #setHouses - I presume your api returns an array .. (?) So make sure you initialize the property (key) in the store (at whatever key #setHouses stores this array) at instantiation so that the store and Vue instances that use the allHouses getter know to watch that array property

  2. #deleteHouses - When you delete the array, you seem to return a new array from the api. If this is true, simply setting the new non-reactive array overtop of the old reactive one will create an unreactive condition. This is a fundamental understanding of Vue's reactivity system - and is likely the cause of your problem.

Fixes:

  1. Whatever key #setHouses uses to set data on the Vuex store, instantiate it as an empty array when the store is created.

  2. #setHouses must iterate response.data and array.push(item) onto this reactive array, rather than simply replace the reactive array with a new (non-reactive) array.

  3. #deleteHouse - should first use array.splice(0) to remove all children in the reactive array, then setHouses will array.push(child) into this reactive array

Update: including examples

//- update: state:
const state = {
  houses: [],
  selectedHouse: null,
};

//- update: #setHouses
  setHouses: (state, houses) => {
    // empty the previous reactive array
    state.houses.splice(0);
    // push the new houses to the original reactive array
    state.houses.push(...houses);
    // state.houses now remains bound to your getters, vue instances and remains reactive
  },

Update: add examples of changes

//- update:state
const state = {
  houses: [],
  selectedHouse: null,
};

//- update:#setHouses
  setHouses: (state, houses) => {
    // empty the previous reactive array
    state.houses.splice(0);
    // push the new houses to the original reactive array
    state.houses.push(...houses);
    // state.houses now remains bound to your getters, vue instances and remains reactive
  },

PS: maybe I'm not clear on what your action #houseDetail does but it seems to re-load ALL houses ... perhaps this is what you want (?)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM