I am managing my state in Angular app by using Behavior Subject. I am using two services. One to perform send and get request using web sockets and one to store the data in an observable. As soon as the data is retrieved I pass the data to the behavior subject. I am having an issue here. Everything is working perfectly except, when I delete the item and press the back button. Some of my data gets lost during this process. I don't know why is this happening. Here's my code:
cart.store.ts // for managing state
private cartItems$ = new BehaviorSubject<Product[]>(null);
private items: Product[] = [];
setCart(cartItems: Product[]) {
this.cartItems$.next(cartItems);
}
setSingleItem(item: Product) {
this.items.push(item);
this.cartItems$.next(this.items);
}
deleteCart(item: Product) {
this.cartItems$.subscribe((res) => {
let index;
for (let i = 0; i < res.length; i ) {
if (item.upc === res[i].upc) {
index = i;
}
}
res.splice(index, 1);
});
}
cart.component.ts //calls cart service and fetches the data
getCartItems() {
if (!this.cartItems?.length) {
const payload = this.localStorageService.getData(LOCAL_STORAGE_KEY.PHONE);
this.cartService.getCart(payload).then((res) => {
//after fetching storing the data
this.cartStore.setCart(res);
for (let x = 0; x < res.length; x ) {
this.totalPrice = this.totalPrice res[x].price;
}
this.cartItems$ = this.cartStore.getCart(); //using async pipe to display in template
});
}
}
cart.service.ts //for getting and removing data
getCart(payload): Promise<any> {
this.socketService.sendMessage(AUTH_EVENTS.ON_DEVICE_CONNECT, payload);
const serverRes = (async () => {
try {
const data = await this.socketService.receivedJustSingleValue(
CART_EVENTS.GET_CART_ITEMS,
);
if (data) {
return data;
} else {
throw new Error('error');
}
} catch (error) {
return error;
}
})();
return serverRes;
}
//remove cart works the same way
When I remove an item and press the back button, my data gets lost. Can anybody tell me what's wrong?
CodePudding user response:
The problem is in the deleteCart
function. You subscribe to the observable but never unsubscribe. So every time you call next()
, The deleteCart
runs again and deletes an item.
You can use BehaviorSubject.value
to get the current items. The result should see like this:
private cartItems$ = new BehaviorSubject<Product[]>(null);
// private items: Product[] = [];
setCart(cartItems: Product[]) {
this.cartItems$.next(cartItems);
}
setSingleItem(item: Product) {
this.cartItems$.next([...this.cartItems$.value, item]);
}
deleteCart(item: Product) {
const items = this.cartItems$.value;
let index;
for (let i = 0; i < items.length; i ) {
if (item.upc === items[i].upc) {
index = i;
}
}
items.splice(index, 1);
this.cartItems$.next(items);
}