Subscribe on changes!

computed() doesn't update when deleting from a ref(Map)

avatar
Sep 30th 2023

Vue version

3.3.4

Link to minimal reproduction

https://play.vuejs.org/#eNrFVt9v2zYQ/lcuwgDb8K+leTMcd93QhwxYF3QF+jANCS2dbTYyKZCUnSDI/76PpKTItedtfWmCKCL53d133/FIPSfvynKyqziZJXObGVk6suyqcpEquS21cfRMmd6WleN8RIZX9EIro7fUg1EvVamaTkluxVoqJrcRDg+m+9LovMqcvadcOOE9sI12QtG72xv8y1u4ZRKGqbEJLsNarlXP0UbsvGuWBhCZwREYUlVOSOn9iPZMe6HgSNMDc0nSgc+2cmJZcHDlQ2lVPMHMB9WB4VJkD34oYPQ03omiAgEhzSisYo6WLNU6jGpidzJv/fnpYBTxiveRW6oyraxrc6Fr+jNVRM/+QSTzGV2O4rsSW55R7xNbdwkhiV7CQgf55hj55jTy6hzyr7pKn5kyw8JB7UD4N1FCvQ1Deq+hLAqyTmNUK9BRBTVp8goFuPY7oV876Q8GdYRaGeXrvfQbYqndJrhrKxKKb9iWcOeDYl1XBjMicxJ1xs7xEe5pK8omaLP/bmtRP8PqtiHSLPb7A7pedDYR0QQ++qtKwbNW1L8rzaAVbUX9GGkSspxshPWAicwHLYjIzwQYAh3A1+waOA2pRz8EtaG3V8K/GDSRUd5BKEMrkdtIi90IkY1cr9lYFMNwnQTJIF3MBxYxfalQti0rF3IGEx85ZHmD6Mg50PUZXZxKqUG2aR2A0Eod0Ih+RNhX/oG7f/i/Al13h5o3NE4J0tIa0qW3ORurdYaYQbhv0yfn763P/1ZnHNXxnF5tFnD+nzh0dQvx6xJ15cs1WxyeF41IUEjv+J8UOgiXM3LhLiRV82m8HHAtYOB4WxY4SDAimudyF0nvxittrtMEnRUsR/4UGXSLdtzBaRJtZ4DCFM84E1zjjHtuOnrizzZ6CakSjfFzhIid+vYt9T7omFK4KZ7Y9U4YzpeVczgXfsoKmT0g9uE+apLwLZ4mi/F4Po0GNbMj88M2/cp8OPw3806BvrL9GFZiQgde5lNIHyqC94vxmCBd+M15Wa2bAfRfaeQdTTam/n+5aI7K+RSDcKG0Utpar0O4r9chOJzBp6DRy/DY5sxZ7v3Mp+3eSkaJs9i8K7mefLFa4QslNEeaeB+yYPN76Q92bKFZ0zZpIopC738Nc87gem7msw1nDyfmv9hHP5cmt7iU2Ow4Tdo1JwwaNy6//+MDP+K9XdyCPz4wzi1+ZKuLynOMsJ8rlYN2BxfY3oTvLHxsfLLvHx0r2yTlib5e92mCL65fzqT+SvdqctWcDMnL35OqU88=

Steps to reproduce

1- Create a new ref with a new Map inside like the following: const prices = ref(new Map()) 2- Define a computed() fn that uses the ref with the Map 3- Delete item from Map and see how that doesn't trigger a recompute. (Keep in mind .set() does trigger a recompute.)

What is expected?

Trigger a recompute when deleting item from Map

What is actually happening?

It doesn't trigger a recompute when deleting an item from Map

System Info

No response

Any additional comments?

No response

avatar
Oct 1st 2023

I believe the computed is recomputing as expected.

The problem is that you're modifying the items in products inside computedProductsWithPrices. That would be considered a side effect and should be avoided. When the price is deleted from the map it is re-running computedProductsWithPrices, but the old value for price is still present on the item in products from the last time it ran.

The debug info you're including in the template is misleading. products is being changed, but the updated version is not being rendered because products in not reactive.

Here's a tweaked version of your example, but with the addition of delete _pr.price inside computedProductsWithPrices to remove the old price. It works fine:

Example

However, as I noted earlier, the computed here still has a side effect. A better way to do this would be to avoid modifying products in the first place by taking a copy of each item before adding the price property:

Example

avatar
Oct 2nd 2023

Ohhh oof, you're 100% right. I thought in my brain that the JS Map was already copying the object for some reason, but it makes sense that it doesn't and just iterates through the references. Thanks for taking the time to reply <3