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:
#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
#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:
Whatever key #setHouses
uses to set data on the Vuex store, instantiate it as an empty array when the store is created.
#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.
#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.