Reputation: 1528
I'm trying to create simple cart system as my first VueJS practice. I start this project from @vue/cli
with Typescript and Vuex and class style-component. Right now, I'm stuck at state object change detection. The state is really update but my component is not re-render.
Here is my state interface. Very simple. Key is ID
of product, Val is amount added to cart.
interface CartItem {
[key: string]: number;
}
Here is my template
<template v-for="book in productLists.books">
<div class="cart-controller">
<button @click="addToCart(id)">-</button>
</div>
<div class="item-in-class">{{ getAmountInCart(book.id) }} In Cart</div>
</template>
I have only one button that use to add product to cart. Later after it added, it should update div.item-in-class
content with number of item added to cart.
Here is my components
<script lang="ts">
import { Vue, Component, Watch } from 'vue-property-decorator';
import { ACTION_TYPE as CART_ACTION_TYPE } from '@/store/modules/cart/actions';
import { ACTION_TYPE as PRODUCT_ACTION_TYPE } from '@/store/modules/product/actions';
@Component
export default class BooksLists extends Vue {
private cart = this.$store.state.cart;
@Watch('this.cart') // try to use watch here, but look like it doesn't work
oncartChange(newVal: any, oldVal: any){
console.log(oldVal);
}
private mounted() {
this.$store.dispatch(PRODUCT_ACTION_TYPE.FETCH_BOOKS);
}
private getAmountInCart(bookId: string): void {
return this.cart.items && this.cart.items[bookId] || 0;
}
private addToCart(bookId: number) {
this.$store.dispatch(CART_ACTION_TYPE.ADD_TO_CART, bookId);
console.log(this.cart);
}
}
</script>
UPDATE 1
my action is also simple. Only receive itemId and commit to Mutation.
Action
const actions: ActionTree<CartState, RootState> = {
[ACTION_TYPE.ADD_TO_CART]({ commit }, item: CartItem): void {
commit(MUTATION_TYPE.ADD_ITEM_TO_CART, item);
},
};
Mutation
const mutations: MutationTree<CartState> = {
[MUTATION_TYPE.ADD_ITEM_TO_CART](state: CartState, payload: number): void {
if (state.items[payload]) {
state.items[payload] += 1;
return;
}
state.items[payload] = 1;
},
};
Upvotes: 0
Views: 1764
Reputation: 2244
For making the change reactive you need to update it as follows:
tempVar = state.items
tempVar['payload'] += 1;
state.items = Object.assign({}, tempVar)
Or
Vue.$set(state.items,'payload',1)
Vue.$set(state.items,'payload',state.items['payload']+1)
for more details refer https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
Upvotes: 2